diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-07-29 20:39:23 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-08-06 22:43:00 +0000 |
commit | 7b0009c2bebe54214f920baf6b2aa4058921777b (patch) | |
tree | 1e5a24cea14540b1e6b8777719487aa47497fa42 /catalog-be/src/main | |
parent | c2f19bdcf5b5d5647770a5d3435d942fb3dd0efa (diff) |
Support for TOSCA functions for Service Import
Reads, interprets and persists property values that uses TOSCA functions
during a Service import.
Change-Id: I6943c447cc743213cb9807d6433cb25fa5effbc3
Issue-ID: SDC-4120
Signed-off-by: André Schmid <andre.schmid@est.tech>
Diffstat (limited to 'catalog-be/src/main')
4 files changed, 510 insertions, 156 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ToscaFunctionYamlParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ToscaFunctionYamlParsingHandler.java new file mode 100644 index 0000000000..6bc74a69df --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ToscaFunctionYamlParsingHandler.java @@ -0,0 +1,180 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; +import org.openecomp.sdc.be.datatypes.elements.CustomYamlFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaStringParameter; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; + +@org.springframework.stereotype.Component +public class ToscaFunctionYamlParsingHandler { + + /** + * Builds a {@link ToscaFunction} based on the property value. It will build the object with the maximum information available in the property + * value, as not all the necessary information can be extracted from it. It will only parse values from supported functions in + * {@link ToscaFunctionType}. + * + * @param toscaFunctionPropertyValueMap the value of a property calls a TOSCA function + * @return the partially filled {@link ToscaFunction} object + */ + public Optional<ToscaFunction> buildToscaFunctionBasedOnPropertyValue(final Map<String, Object> toscaFunctionPropertyValueMap) { + if (!isPropertyValueToscaFunction(toscaFunctionPropertyValueMap)) { + return Optional.empty(); + } + final String functionType = toscaFunctionPropertyValueMap.keySet().iterator().next(); + final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType(functionType).orElse(null); + if (toscaFunctionType == null) { + return Optional.empty(); + } + switch (toscaFunctionType) { + case GET_INPUT: { + return handleGetInputFunction(toscaFunctionPropertyValueMap, functionType); + } + case GET_PROPERTY: + case GET_ATTRIBUTE: { + return handleGetPropertyFunction(toscaFunctionPropertyValueMap, functionType, toscaFunctionType); + } + case CONCAT: + return handleConcatFunction(toscaFunctionPropertyValueMap, functionType); + default: + return Optional.empty(); + } + } + + /** + * Checks if the property value is a supported TOSCA function. + * + * @param propValueObj the value of a property + * @return {@code true} if the value is a supported TOSCA function, {@code false} otherwise + */ + public boolean isPropertyValueToscaFunction(final Object propValueObj) { + if (propValueObj instanceof Map) { + final Map<String, Object> propValueMap = (Map<String, Object>) propValueObj; + if (propValueMap.keySet().size() > 1) { + return false; + } + return Stream.of(ToscaFunctionType.GET_INPUT, ToscaFunctionType.GET_PROPERTY, ToscaFunctionType.GET_ATTRIBUTE, ToscaFunctionType.CONCAT) + .anyMatch(type -> propValueMap.containsKey(type.getName())); + } + return false; + } + + private Optional<ToscaFunction> handleConcatFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) { + final ToscaConcatFunction toscaConcatFunction = new ToscaConcatFunction(); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List)) { + return Optional.empty(); + } + final List<Object> functionParameters = (List<Object>) functionValueObj; + if (functionParameters.size() < 2) { + return Optional.empty(); + } + functionParameters.forEach(parameter -> { + if (parameter instanceof String) { + final var stringParameter = new ToscaStringParameter(); + stringParameter.setValue((String) parameter); + toscaConcatFunction.addParameter(stringParameter); + return; + } + if (isPropertyValueToscaFunction(parameter)) { + buildToscaFunctionBasedOnPropertyValue((Map<String, Object>) parameter).ifPresent(toscaFunction -> { + if (toscaFunction instanceof ToscaFunctionParameter) { + toscaConcatFunction.addParameter((ToscaFunctionParameter) toscaFunction); + } + }); + return; + } + final var customYamlFunction = new CustomYamlFunction(); + customYamlFunction.setYamlValue(parameter); + toscaConcatFunction.addParameter(customYamlFunction); + }); + return Optional.of(toscaConcatFunction); + } + + private static Optional<ToscaFunction> handleGetPropertyFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType, + ToscaFunctionType toscaFunctionType) { + final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition(); + toscaGetFunction.setFunctionType( + toscaFunctionType == ToscaFunctionType.GET_PROPERTY ? ToscaGetFunctionType.GET_PROPERTY : ToscaGetFunctionType.GET_ATTRIBUTE + ); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List)) { + return Optional.empty(); + } + final List<String> functionParameters; + try { + functionParameters = (List<String>) functionValueObj; + } catch (final ClassCastException ignored) { + return Optional.empty(); + } + if (functionParameters.size() < 2) { + return Optional.empty(); + } + final String propertySourceType = functionParameters.get(0); + final PropertySource propertySource = PropertySource.findType(propertySourceType).orElse(null); + if (propertySource == PropertySource.SELF) { + toscaGetFunction.setPropertySource(propertySource); + } else { + toscaGetFunction.setPropertySource(PropertySource.INSTANCE); + toscaGetFunction.setSourceName(propertySourceType); + } + toscaGetFunction.setPropertyPathFromSource(functionParameters.subList(1, functionParameters.size())); + final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1); + toscaGetFunction.setPropertyName(propertyName); + return Optional.of(toscaGetFunction); + } + + private static Optional<ToscaFunction> handleGetInputFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) { + final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition(); + toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT); + toscaGetFunction.setPropertySource(PropertySource.SELF); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List) && !(functionValueObj instanceof String)) { + return Optional.empty(); + } + if (functionValueObj instanceof String) { + toscaGetFunction.setPropertyPathFromSource(List.of((String) functionValueObj)); + } else { + final List<String> functionParameters; + try { + functionParameters = (List<String>) functionValueObj; + } catch (final ClassCastException ignored) { + return Optional.empty(); + } + toscaGetFunction.setPropertyPathFromSource(functionParameters); + } + final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1); + toscaGetFunction.setPropertyName(propertyName); + return Optional.of(toscaGetFunction); + } + +} 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 a68bbf3a2d..cbba46f35c 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 @@ -77,7 +77,6 @@ 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.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -88,7 +87,6 @@ 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.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; @@ -130,22 +128,24 @@ import org.yaml.snakeyaml.parser.ParserException; @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; + private final Gson gson = new Gson(); + private final JanusGraphDao janusGraphDao; + private final GroupTypeBusinessLogic groupTypeBusinessLogic; + private final AnnotationBusinessLogic annotationBusinessLogic; + private final PolicyTypeBusinessLogic policyTypeBusinessLogic; + private final ToscaFunctionYamlParsingHandler toscaFunctionYamlParsingHandler; public YamlTemplateParsingHandler(JanusGraphDao janusGraphDao, GroupTypeBusinessLogic groupTypeBusinessLogic, - AnnotationBusinessLogic annotationBusinessLogic, PolicyTypeBusinessLogic policyTypeBusinessLogic) { + AnnotationBusinessLogic annotationBusinessLogic, PolicyTypeBusinessLogic policyTypeBusinessLogic, + final ToscaFunctionYamlParsingHandler toscaFunctionYamlParsingHandler) { this.janusGraphDao = janusGraphDao; this.groupTypeBusinessLogic = groupTypeBusinessLogic; this.annotationBusinessLogic = annotationBusinessLogic; this.policyTypeBusinessLogic = policyTypeBusinessLogic; + this.toscaFunctionYamlParsingHandler = toscaFunctionYamlParsingHandler; } public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map<String, String> createdNodesToscaResourceNames, @@ -306,31 +306,36 @@ public class YamlTemplateParsingHandler { return policyTypeDefinition; } - private List<PropertyDataDefinition> validateFillPolicyProperties(PolicyTypeDefinition policyTypeDefinition, - Map<String, Object> policyTemplateJsonMap) { - if (MapUtils.isEmpty(policyTemplateJsonMap) || Objects.isNull(policyTypeDefinition)) { + private List<PropertyDataDefinition> validateFillPolicyProperties(final PolicyTypeDefinition policyTypeDefinition, + final Map<String, Object> policyTemplateJsonMap) { + if (policyTypeDefinition == null || CollectionUtils.isEmpty(policyTypeDefinition.getProperties()) + || MapUtils.isEmpty(policyTemplateJsonMap)) { return Collections.emptyList(); } - List<PropertyDataDefinition> propertyDataDefinitionList = new ArrayList<>(); - Map<String, Object> propertiesMap = (Map<String, Object>) policyTemplateJsonMap.get(PROPERTIES.getElementName()); - if (MapUtils.isEmpty(propertiesMap)) { + final Map<String, Object> propertiesJsonMap = (Map<String, Object>) 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<String, Object> 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.setValue(gson.toJson(uploadPropInfo.getValue())); + propertyDefinition.setToscaFunction(uploadPropInfo.getToscaFunction()); + propertyDefinition.setGetInputValues(uploadPropInfo.getGet_input()); + propertyDefinition.setDescription(uploadPropInfo.getDescription()); + return propertyDefinition; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } private Map<PolicyTargetType, List<String>> validateFillPolicyTargets(Map<String, Object> policyTemplateJson) { @@ -473,8 +478,8 @@ public class YamlTemplateParsingHandler { .collect(Collectors.toMap(GroupDefinition::getName, g -> g)); Map<String, Object> substitutionMappings = getSubstitutionMappings(toscaJson); if (capabilitiesSubstitutionMappingsExist(substitutionMappings)) { - groups.entrySet().forEach(entry -> updateCapabilitiesNames(entry.getValue(), - getNamesToUpdate(entry.getKey(), (Map<String, List<String>>) substitutionMappings.get(CAPABILITIES.getElementName())))); + groups.forEach((key, value) -> updateCapabilitiesNames(value, + getNamesToUpdate(key, (Map<String, List<String>>) substitutionMappings.get(CAPABILITIES.getElementName())))); } return groups; } @@ -555,28 +560,21 @@ public class YamlTemplateParsingHandler { } } - private void mergeGroupProperties(GroupDefinition groupInfo, Map<String, Object> parsedProperties) { - if (CollectionUtils.isNotEmpty(groupInfo.getProperties())) { - validateGroupProperties(parsedProperties, groupInfo); - groupInfo.getProperties().forEach(p -> mergeGroupProperty(p, parsedProperties)); - } - } - - private void mergeGroupProperty(PropertyDataDefinition property, Map<String, Object> parsedProperties) { - if (parsedProperties.containsKey(property.getName())) { - Object propValue = parsedProperties.get(property.getName()); - if (valueNotContainsPattern(propertyValuePattern, propValue)) { - setPropertyValueAndGetInputsValues(property, propValue); - } + private void mergeGroupProperties(final GroupDefinition groupDefinition, final Map<String, Object> 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 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.setValue(convertPropertyValue(ToscaPropertyType.isValidType(property.getType()), uploadPropInfo.getValue())); + property.setGetInputValues(uploadPropInfo.getGet_input()); } private String convertPropertyValue(ToscaPropertyType type, Object value) { @@ -675,7 +673,7 @@ public class YamlTemplateParsingHandler { } private void validateGroupProperties(Map<String, Object> parsedProperties, GroupDefinition groupInfo) { - List<String> parsedPropertiesNames = parsedProperties.entrySet().stream().map(Map.Entry::getKey).collect(toList()); + List<String> parsedPropertiesNames = new ArrayList<>(parsedProperties.keySet()); validateProperties(groupInfo.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.GROUP_PROPERTY_NOT_FOUND, groupInfo.getName(), groupInfo.getType()); } @@ -788,7 +786,8 @@ public class YamlTemplateParsingHandler { private void updateProperties(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { - Map<String, List<UploadPropInfo>> properties = buildPropModuleFromYaml(nodeTemplateJsonMap); + Map<String, List<UploadPropInfo>> properties = + buildPropModuleFromYaml((Map<String, Object>) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); if (!properties.isEmpty()) { nodeTemplateInfo.setProperties(properties); } @@ -942,7 +941,8 @@ public class YamlTemplateParsingHandler { artifactTemplateInfo.setFile((String) nodeTemplateJsonMap.get(FILE.getElementName())); } if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { - Map<String, List<UploadPropInfo>> props = buildPropModuleFromYaml(nodeTemplateJsonMap); + Map<String, List<UploadPropInfo>> props = + buildPropModuleFromYaml((Map<String, Object>) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); if (!props.isEmpty()) { List<UploadPropInfo> properties = props.values().stream().flatMap(Collection::stream).collect(toList()); artifactTemplateInfo.setProperties(properties); @@ -1011,7 +1011,8 @@ public class YamlTemplateParsingHandler { } } if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { - Map<String, List<UploadPropInfo>> props = buildPropModuleFromYaml(nodeTemplateJsonMap); + Map<String, List<UploadPropInfo>> props = + buildPropModuleFromYaml((Map<String, Object>) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); if (!props.isEmpty()) { List<UploadPropInfo> properties = props.values().stream().flatMap(Collection::stream).collect(toList()); capTemplateInfo.setProperties(properties); @@ -1063,17 +1064,9 @@ public class YamlTemplateParsingHandler { return attributeDef; } - private Map<String, List<UploadPropInfo>> buildPropModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) { - Map<String, List<UploadPropInfo>> moduleProp = new HashMap<>(); - Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(nodeTemplateJsonMap, PROPERTIES); - if (toscaProperties.isLeft()) { - Map<String, Object> jsonProperties = toscaProperties.left().value(); - for (Map.Entry<String, Object> jsonPropObj : jsonProperties.entrySet()) { - if (valueNotContainsPattern(propertyValuePattern, jsonPropObj.getValue())) { - addProperty(moduleProp, jsonPropObj); - } - } - } + private Map<String, List<UploadPropInfo>> buildPropModuleFromYaml(final Map<String, Object> propertyMap) { + final Map<String, List<UploadPropInfo>> moduleProp = new HashMap<>(); + propertyMap.entrySet().forEach(propertyMapEntry -> addProperty(moduleProp, propertyMapEntry)); return moduleProp; } @@ -1089,32 +1082,35 @@ public class YamlTemplateParsingHandler { } @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<String, Object>) propValue).containsKey(TYPE.getElementName())) { - propertyDef.setType(((Map<String, Object>) propValue).get(TYPE.getElementName()).toString()); + if (propValueObj instanceof Map) { + final Map<String, Object> propValueMap = (Map<String, Object>) propValueObj; + if (propValueMap.containsKey(TYPE.getElementName())) { + propertyDef.setType(propValueMap.get(TYPE.getElementName()).toString()); } - if (containsGetInput(propValue)) { - fillInputRecursively(propName, (Map<String, Object>) propValue, propertyDef); + if (containsGetInput(propValueObj)) { + fillInputRecursively(propName, propValueMap, propertyDef); } - if (((Map<String, Object>) propValue).containsKey(DESCRIPTION.getElementName())) { - propertyDef.setDescription(((Map<String, Object>) propValue).get(DESCRIPTION.getElementName()).toString()); + if (toscaFunctionYamlParsingHandler.isPropertyValueToscaFunction(propValueObj)) { + toscaFunctionYamlParsingHandler.buildToscaFunctionBasedOnPropertyValue(propValueMap).ifPresent(propertyDef::setToscaFunction); } - if (((Map<String, Object>) propValue).containsKey(DEFAULT_VALUE.getElementName())) { - propertyDef.setValue(((Map<String, Object>) propValue).get(DEFAULT_VALUE.getElementName())); + if (propValueMap.containsKey(DESCRIPTION.getElementName())) { + propertyDef.setDescription((propValueMap).get(DESCRIPTION.getElementName()).toString()); } - if (((Map<String, Object>) propValue).containsKey(IS_PASSWORD.getElementName())) { - propertyDef.setPassword(Boolean.getBoolean(((Map<String, Object>) propValue).get(IS_PASSWORD.getElementName()).toString())); + if (propValueMap.containsKey(DEFAULT_VALUE.getElementName())) { + propertyDef.setValue(propValueMap.get(DEFAULT_VALUE.getElementName())); + } + 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<Object> propValueList = (List<Object>) propValue; - fillInputsListRecursively(propertyDef, propValueList); - propertyDef.setValue(propValue); + } else if (propValueObj instanceof List) { + fillInputsListRecursively(propertyDef, (List<Object>) propValueObj); + propertyDef.setValue(propValueObj); } return propertyDef; } @@ -1217,10 +1213,6 @@ public class YamlTemplateParsingHandler { } } - private boolean valueNotContainsPattern(Pattern pattern, Object propValue) { - return propValue == null || !pattern.matcher(propValue.toString()).find(); - } - private Object failIfNotTopologyTemplate(String fileName) { janusGraphDao.rollback(); throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index 0850535108..7e15a52b90 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -33,9 +33,12 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.Getter; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; @@ -45,7 +48,6 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; -import org.openecomp.sdc.be.components.distribution.engine.IDistributionEngine; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; @@ -56,16 +58,6 @@ import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.merge.resource.ResourceDataMergeBusinessLogic; -import org.openecomp.sdc.be.components.path.ForwardingPathValidator; -import org.openecomp.sdc.be.components.validation.NodeFilterValidator; -import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation; -import org.openecomp.sdc.be.components.validation.component.ComponentContactIdValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentDescriptionValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentIconValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentNameValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentProjectCodeValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentTagsValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentValidator; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -76,6 +68,8 @@ import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; @@ -88,6 +82,7 @@ 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.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; @@ -118,19 +113,11 @@ import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeFilterOperation; 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.StorageException; -import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; -import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; -import org.openecomp.sdc.be.model.operations.api.IGroupOperation; -import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.be.ui.model.OperationUi; @@ -179,19 +166,12 @@ public class ServiceImportBusinessLogic { private final JanusGraphDao janusGraphDao; private final ArtifactsBusinessLogic artifactsBusinessLogic; private final IGraphLockOperation graphLockOperation; + private final ToscaFunctionService toscaFunctionService; - public ServiceImportBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation, - IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic, - InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation, - ArtifactsBusinessLogic artifactsBusinessLogic, IDistributionEngine distributionEngine, - ComponentInstanceBusinessLogic componentInstanceBusinessLogic, - ServiceDistributionValidation serviceDistributionValidation, ForwardingPathValidator forwardingPathValidator, - UiComponentDataConverter uiComponentDataConverter, NodeFilterOperation serviceFilterOperation, - NodeFilterValidator serviceFilterValidator, ArtifactsOperations artifactToscaOperation, - ComponentContactIdValidator componentContactIdValidator, ComponentNameValidator componentNameValidator, - ComponentTagsValidator componentTagsValidator, ComponentValidator componentValidator, - ComponentIconValidator componentIconValidator, ComponentProjectCodeValidator componentProjectCodeValidator, - ComponentDescriptionValidator componentDescriptionValidator, final ComponentsUtils componentsUtils, + public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic, + final ArtifactsBusinessLogic artifactsBusinessLogic, + final ComponentInstanceBusinessLogic componentInstanceBusinessLogic, + final UiComponentDataConverter uiComponentDataConverter, final ComponentsUtils componentsUtils, final ToscaOperationFacade toscaOperationFacade, final ServiceBusinessLogic serviceBusinessLogic, final CsarBusinessLogic csarBusinessLogic, final CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic, @@ -200,7 +180,7 @@ public class ServiceImportBusinessLogic { final ServiceImportParseLogic serviceImportParseLogic, final ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic, final PolicyBusinessLogic policyBusinessLogic, final JanusGraphDao janusGraphDao, - final IGraphLockOperation graphLockOperation) { + final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService) { this.componentInstanceBusinessLogic = componentInstanceBusinessLogic; this.uiComponentDataConverter = uiComponentDataConverter; this.componentsUtils = componentsUtils; @@ -218,6 +198,7 @@ public class ServiceImportBusinessLogic { this.janusGraphDao = janusGraphDao; this.artifactsBusinessLogic = artifactsBusinessLogic; this.graphLockOperation = graphLockOperation; + this.toscaFunctionService = toscaFunctionService; } public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map<String, byte[]> csarUIPayload, @@ -239,8 +220,11 @@ public class ServiceImportBusinessLogic { csarBusinessLogic.validateCsarBeforeCreate(service, csarUUID); log.debug("CsarUUID is {} - going to create resource from CSAR", csarUUID); return createServiceFromCsar(service, user, csarUIPayload, csarUUID); - } catch (Exception e) { - log.debug("Exception occured when createService,error is:{}", e.getMessage(), e); + } catch (final ComponentException e) { + log.debug("Exception occurred when createService: {}", e.getMessage(), e); + throw e; + } catch (final Exception e) { + log.debug("Exception occurred when createService: {}", e.getMessage(), e); throw new ComponentException(ActionStatus.GENERAL_ERROR); } } @@ -258,8 +242,11 @@ public class ServiceImportBusinessLogic { } return createServiceFromYaml(service, csarInfo.getMainTemplateContent(), csarInfo.getMainTemplateName(), nodeTypesInfo, csarInfo, findNodeTypesArtifactsToHandleRes.left().value(), true, false, null, user.getUserId()); - } catch (Exception e) { - log.debug("Exception occured when createServiceFromCsar,error is:{}", e.getMessage(), e); + } catch (final ComponentException e) { + log.debug("Exception occurred when createServiceFromCsar,error is:{}", e.getMessage(), e); + throw e; + } catch (final Exception e) { + log.debug("Exception occurred when createServiceFromCsar,error is:{}", e.getMessage(), e); throw new ComponentException(ActionStatus.GENERAL_ERROR); } } @@ -925,13 +912,27 @@ public class ServiceImportBusinessLogic { return getServiceResponseFormatEither(service); } - private Either<Service, ResponseFormat> createPoliciesOnResource(Service service, - Map<String, PolicyDefinition> policies) { - if (MapUtils.isNotEmpty(policies)) { - policyBusinessLogic.createPolicies(service, policies); - } else { + private Either<Service, ResponseFormat> createPoliciesOnResource(final Service service, + final Map<String, PolicyDefinition> policies) { + if (MapUtils.isEmpty(policies)) { return Either.left(service); } + final Map<String, List<AttributeDefinition>> instanceAttributeMap = + service.getComponentInstancesAttributes() + .entrySet().stream() + .collect( + toMap(Entry::getKey, + entry -> entry.getValue().stream().map(AttributeDefinition.class::cast).collect(toList())) + ); + policies.values().stream() + .map(PolicyDataDefinition::getProperties) + .flatMap(Collection::stream) + .filter(PropertyDataDefinition::isToscaFunction) + .forEach(policyDefinition -> + toscaFunctionService + .updateFunctionWithDataFromSelfComponent(policyDefinition.getToscaFunction(), service, service.getComponentInstancesProperties(), instanceAttributeMap) + ); + policyBusinessLogic.createPolicies(service, policies); return getServiceResponseFormatEither(service); } @@ -1357,7 +1358,7 @@ public class ServiceImportBusinessLogic { Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { log.debug("#createResourceInstancesRelations - Going to create relations "); List<ComponentInstance> componentInstancesList = service.getComponentInstances(); - if (((MapUtils.isEmpty(uploadResInstancesMap) || CollectionUtils.isEmpty(componentInstancesList)))) { // PNF can have no resource instances + if (MapUtils.isEmpty(uploadResInstancesMap) || CollectionUtils.isEmpty(componentInstancesList)) { // PNF can have no resource instances log.debug("#createResourceInstancesRelations - No instances found in the resource {} is empty, yaml template file name {}, ", service.getUniqueId(), yamlName); BeEcompErrorManager.getInstance() @@ -1378,13 +1379,16 @@ public class ServiceImportBusinessLogic { log.debug("enter ServiceImportBusinessLogic createServiceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. "); final ApplicationDataTypeCache applicationDataTypeCache = serviceBusinessLogic.applicationDataTypeCache; if (applicationDataTypeCache != null) { - Service finalResource = service; + final Map<String, DataTypeDefinition> allDataTypesMap = + componentsUtils.getAllDataTypes(applicationDataTypeCache, service.getModel()); + final Service service1 = service; uploadResInstancesMap.values().forEach( - i -> processComponentInstance(yamlName, finalResource, componentInstancesList, - componentsUtils.getAllDataTypes(applicationDataTypeCache, finalResource.getModel()), instProperties, + i -> processComponentInstance(yamlName, service1, componentInstancesList, + allDataTypesMap, instProperties, instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs, instNodeFilter, i)); } + updatePropertyToscaFunctionData(service, instProperties, instAttributes); serviceImportParseLogic.associateComponentInstancePropertiesToComponent(yamlName, service, instProperties); serviceImportParseLogic.associateComponentInstanceInputsToComponent(yamlName, service, instInputs); serviceImportParseLogic.associateCINodeFilterToComponent(yamlName, service, instNodeFilter); @@ -1412,6 +1416,29 @@ public class ServiceImportBusinessLogic { return eitherGetResource.left().value(); } + private void updatePropertyToscaFunctionData(final Component service, + final Map<String, List<ComponentInstanceProperty>> instancePropertyMap, + final Map<String, List<AttributeDefinition>> instanceAttributeMap) { + final Component updatedService = + toscaOperationFacade.getToscaElement(service.getUniqueId()).left() + .on(storageOperationStatus -> { + final ActionStatus status = componentsUtils.convertFromStorageResponse(storageOperationStatus); + final ResponseFormat responseFormat = + componentsUtils.getResponseFormatByComponent(status, service, service.getComponentType()); + throw new ComponentException(responseFormat); + } + ); + instancePropertyMap.values().forEach(instancePropertyList -> + instancePropertyList.stream() + .filter(PropertyDataDefinition::isToscaFunction) + .forEach(instanceProperty -> { + toscaFunctionService.updateFunctionWithDataFromSelfComponent(instanceProperty.getToscaFunction(), + updatedService, instancePropertyMap, instanceAttributeMap); + instanceProperty.setValue(instanceProperty.getToscaFunction().getValue()); + }) + ); + } + protected void processComponentInstance(String yamlName, Component component, List<ComponentInstance> componentInstancesList, Map<String, DataTypeDefinition> allDataTypes, Map<String, List<ComponentInstanceProperty>> instProperties, @@ -1426,7 +1453,7 @@ public class ServiceImportBusinessLogic { log.debug("enter ServiceImportBusinessLogic processComponentInstance"); Optional<ComponentInstance> currentCompInstanceOpt = componentInstancesList.stream() .filter(i -> i.getName().equals(uploadComponentInstanceInfo.getName())).findFirst(); - if (!currentCompInstanceOpt.isPresent()) { + if (currentCompInstanceOpt.isEmpty()) { log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), component.getUniqueId()); BeEcompErrorManager.getInstance() .logInternalDataError(COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, component.getUniqueId(), @@ -1542,23 +1569,20 @@ public class ServiceImportBusinessLogic { Map<String, DataTypeDefinition> allDataTypes) { Map<String, List<UploadPropInfo>> propMap = uploadComponentInstanceInfo.getProperties(); Map<String, PropertyDefinition> currPropertiesMap = new HashMap<>(); - List<PropertyDefinition> listFromMap = originResource.getProperties(); - if ((propMap != null && !propMap.isEmpty()) && (listFromMap == null || listFromMap.isEmpty())) { + List<PropertyDefinition> originalPropertyList = originResource.getProperties(); + if (MapUtils.isNotEmpty(propMap) && CollectionUtils.isEmpty(originalPropertyList)) { log.debug("failed to find properties "); return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); } - if (listFromMap == null || listFromMap.isEmpty()) { + if (CollectionUtils.isEmpty(originalPropertyList)) { return componentsUtils.getResponseFormat(ActionStatus.OK); } - for (PropertyDefinition prop : listFromMap) { - String propName = prop.getName(); - if (!currPropertiesMap.containsKey(propName)) { - currPropertiesMap.put(propName, prop); - } - } + originalPropertyList.stream() + .filter(property -> !currPropertiesMap.containsKey(property.getName())) + .forEach(property -> currPropertiesMap.put(property.getName(), property)); List<ComponentInstanceProperty> instPropList = new ArrayList<>(); - if (propMap != null && propMap.size() > 0) { - for (List<UploadPropInfo> propertyList : propMap.values()) { + if (MapUtils.isNotEmpty(propMap)) { + for (final List<UploadPropInfo> propertyList : propMap.values()) { UploadPropInfo propertyInfo = propertyList.get(0); String propName = propertyInfo.getName(); if (!currPropertiesMap.containsKey(propName)) { @@ -1566,26 +1590,26 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, propName); } PropertyDefinition curPropertyDef = currPropertiesMap.get(propName); - ComponentInstanceProperty property = null; String value = null; - List<GetInputValueDataDefinition> getInputs = null; + final List<GetInputValueDataDefinition> getInputs = new ArrayList<>(); boolean isValidate = true; if (propertyInfo.getValue() != null) { - getInputs = propertyInfo.getGet_input(); - isValidate = getInputs == null || getInputs.isEmpty(); + getInputs.addAll(propertyInfo.getGet_input()); + isValidate = getInputs.isEmpty(); if (isValidate) { value = getPropertyJsonStringValue(propertyInfo.getValue(), curPropertyDef.getType()); } else { value = getPropertyJsonStringValue(propertyInfo.getValue(), TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); } } - property = new ComponentInstanceProperty(curPropertyDef, value, null); + final var property = new ComponentInstanceProperty(curPropertyDef, value, null); String validatePropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); property.setValue(validatePropValue); - if (getInputs != null && !getInputs.isEmpty()) { - List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); - for (GetInputValueDataDefinition getInput : getInputs) { - List<InputDefinition> inputs = component.getInputs(); + property.setToscaFunction(propertyInfo.getToscaFunction()); + if (!getInputs.isEmpty()) { + final List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); + for (final GetInputValueDataDefinition getInput : getInputs) { + final List<InputDefinition> inputs = component.getInputs(); if (inputs == null || inputs.isEmpty()) { log.debug("Failed to add property {} to instance. Inputs list is empty ", property); serviceBusinessLogic.rollbackWithException(ActionStatus.INPUTS_NOT_FOUND, @@ -2407,7 +2431,7 @@ public class ServiceImportBusinessLogic { .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); throw new ComponentException(errorResponse); } - if (eitherValidation.left().value()) { + if (Boolean.TRUE.equals(eitherValidation.left().value())) { log.debug("resource with name: {}, already exists", resource.getName()); ResponseFormat errorResponse = componentsUtils .getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, ComponentTypeEnum.RESOURCE.getValue(), resource.getName()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ToscaFunctionService.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ToscaFunctionService.java new file mode 100644 index 0000000000..28843af54a --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ToscaFunctionService.java @@ -0,0 +1,158 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + +import java.util.List; +import java.util.Map; +import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.model.AttributeDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; + +@org.springframework.stereotype.Service +public class ToscaFunctionService { + + final List<ToscaFunctionType> functionTypesToUpdateList = + List.of(ToscaFunctionType.GET_INPUT, ToscaFunctionType.GET_ATTRIBUTE, ToscaFunctionType.GET_PROPERTY, ToscaFunctionType.CONCAT); + + /** + * Sets the sourceUniqueId, sourceName and propertyUniqueId values in a ToscaFunction based on values from the given component. This method may be + * useful during creation of a ToscaFunction where these values are not otherwise provided. + * + * @param toscaFunctionToUpdate the TOSCA function to update + * @param selfComponent the SELF Component + * @param instancePropertyMap the SELF Component instances properties + * @param instanceAttributeMap the SELF Component instances attributes + */ + public void updateFunctionWithDataFromSelfComponent(final ToscaFunction toscaFunctionToUpdate, final Component selfComponent, + final Map<String, List<ComponentInstanceProperty>> instancePropertyMap, + final Map<String, List<AttributeDefinition>> instanceAttributeMap) { + switch (toscaFunctionToUpdate.getType()) { + case GET_INPUT: { + updateGetInputFunction((ToscaGetFunctionDataDefinition) toscaFunctionToUpdate, selfComponent); + break; + } + case GET_PROPERTY: + case GET_ATTRIBUTE: { + updateGetPropertyFunction((ToscaGetFunctionDataDefinition) toscaFunctionToUpdate, selfComponent, instancePropertyMap, + instanceAttributeMap); + break; + } + case CONCAT: + updateConcatFunction((ToscaConcatFunction) toscaFunctionToUpdate, selfComponent, instancePropertyMap, instanceAttributeMap); + break; + } + } + + /** + * Updates the TOSCA concat function parameters, where the parameter is a TOSCA function. + * + * @param concatFunction the TOSCA concat function to update + * @param selfComponent the SELF component + * @param instancePropertyMap the component instances properties + * @param instanceAttributeMap the component instances attributes + */ + private void updateConcatFunction(final ToscaConcatFunction concatFunction, final Component selfComponent, + final Map<String, List<ComponentInstanceProperty>> instancePropertyMap, + final Map<String, List<AttributeDefinition>> instanceAttributeMap) { + concatFunction.getParameters().stream() + .filter(ToscaFunction.class::isInstance) + .filter(functionParameter -> functionTypesToUpdateList.contains(functionParameter.getType())) + .forEach(functionParameter -> + updateFunctionWithDataFromSelfComponent((ToscaFunction) functionParameter, selfComponent, instancePropertyMap, instanceAttributeMap)); + } + + /** + * Updates the Source Unique Id, the Source Name and the Property Unique Id of the TOSCA get_input function. + * + * @param toscaGetFunction the TOSCA get_input function to update + * @param selfComponent the SELF component + */ + private void updateGetInputFunction(final ToscaGetFunctionDataDefinition toscaGetFunction, final Component selfComponent) { + toscaGetFunction.setSourceUniqueId(selfComponent.getUniqueId()); + toscaGetFunction.setSourceName(selfComponent.getName()); + selfComponent.getInputs().stream() + .filter(inputDefinition -> inputDefinition.getName().equals(toscaGetFunction.getPropertyName())) + .findAny().ifPresent(input -> + toscaGetFunction.setPropertyUniqueId(input.getUniqueId()) + ); + } + + /** + * Updates the Source Unique Id, the Source Name and the Property Unique Id of the TOSCA get function. + * + * @param toscaGetFunction the TOSCA get function to update + * @param selfComponent the SELF component + * @param instancePropertyMap the component instances properties + * @param instanceAttributeMap the component instances attributes + */ + private void updateGetPropertyFunction(final ToscaGetFunctionDataDefinition toscaGetFunction, final Component selfComponent, + final Map<String, List<ComponentInstanceProperty>> instancePropertyMap, + final Map<String, List<AttributeDefinition>> instanceAttributeMap) { + if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { + toscaGetFunction.setSourceUniqueId(selfComponent.getUniqueId()); + toscaGetFunction.setSourceName(selfComponent.getName()); + if (toscaGetFunction.getType() == ToscaFunctionType.GET_PROPERTY) { + selfComponent.getProperties().stream() + .filter(property -> property.getName().equals(toscaGetFunction.getPropertyPathFromSource().get(0))) + .findAny() + .ifPresent(property -> + toscaGetFunction.setPropertyUniqueId(property.getUniqueId()) + ); + } else { + selfComponent.getAttributes().stream() + .filter(attribute -> attribute.getName().equals(toscaGetFunction.getPropertyPathFromSource().get(0))) + .findAny() + .ifPresent(attribute -> + toscaGetFunction.setPropertyUniqueId(attribute.getUniqueId()) + ); + } + } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { + selfComponent.getComponentInstances().stream() + .filter(componentInstance -> toscaGetFunction.getSourceName().equals(componentInstance.getName())) + .findAny() + .ifPresent(componentInstance -> toscaGetFunction.setSourceUniqueId(componentInstance.getUniqueId())); + if (toscaGetFunction.getType() == ToscaFunctionType.GET_PROPERTY) { + final List<ComponentInstanceProperty> instanceProperties = instancePropertyMap.get(toscaGetFunction.getSourceUniqueId()); + instanceProperties.stream() + .filter(property -> property.getName().equals(toscaGetFunction.getPropertyPathFromSource().get(0))) + .findAny() + .ifPresent(property -> + toscaGetFunction.setPropertyUniqueId(property.getUniqueId()) + ); + } else { + final List<AttributeDefinition> instanceAttributes = instanceAttributeMap.get(toscaGetFunction.getSourceUniqueId()); + instanceAttributes.stream() + .filter(attribute -> attribute.getName().equals(toscaGetFunction.getPropertyPathFromSource().get(0))) + .findAny() + .ifPresent(attribute -> + toscaGetFunction.setPropertyUniqueId(attribute.getUniqueId()) + ); + } + } + } + +} |