Import services with sub prop tosca functions
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ServiceImportBusinessLogic.java
index 8c46285..ccf7e5c 100644 (file)
@@ -25,6 +25,9 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonSt
 import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN;
 
 import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 import fj.data.Either;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -40,6 +43,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.collections.CollectionUtils;
@@ -78,6 +82,7 @@ import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubPropertyToscaFunction;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -131,6 +136,7 @@ import org.openecomp.sdc.be.model.operations.StorageException;
 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
@@ -1892,10 +1898,17 @@ public class ServiceImportBusinessLogic {
                     }
                 }
                 final var property = new ComponentInstanceProperty(curPropertyDef, value, null);
-                String validatePropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes);
-                property.setValue(validatePropValue);
+                String validatedPropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, true, allDataTypes);
                 
-                if (tryHandlingAsYamlToscaFunction(validatePropValue, value, propertyInfo)) {
+                addSubPropertyYamlToscaFunctions(validatedPropValue, value, property.getType(), propertyInfo, allDataTypes);
+                
+                if (CollectionUtils.isNotEmpty(propertyInfo.getSubPropertyToscaFunctions())) {
+                    validatedPropValue = value;
+                }
+
+                property.setValue(validatedPropValue);
+
+                if (tryHandlingAsYamlToscaFunction(validatedPropValue, value, propertyInfo)) {
                     try {
                         final Object yamlValue = new Yaml().loadAs(value, Object.class);
                         CustomYamlFunction toscaFunction = new CustomYamlFunction();
@@ -1907,7 +1920,8 @@ public class ServiceImportBusinessLogic {
                 } else {
                     property.setToscaFunction(propertyInfo.getToscaFunction());
                 }
-                if (!getInputs.isEmpty()) {
+                property.setSubPropertyToscaFunctions(propertyInfo.getSubPropertyToscaFunctions());
+                if (!getInputs.isEmpty() && CollectionUtils.isEmpty(property.getSubPropertyToscaFunctions())) {
                     final List<GetInputValueDataDefinition> getInputValues = new ArrayList<>();
                     for (final GetInputValueDataDefinition getInput : getInputs) {
                         final List<InputDefinition> inputs = component.getInputs();
@@ -1941,8 +1955,63 @@ public class ServiceImportBusinessLogic {
         return componentsUtils.getResponseFormat(ActionStatus.OK);
     }
     
-    private boolean tryHandlingAsYamlToscaFunction(String validatePropValue, String value, UploadPropInfo propertyInfo) {
-        return StringUtils.isEmpty(validatePropValue) && StringUtils.isNotEmpty(value) && propertyInfo.getToscaFunction() == null;
+    private boolean tryHandlingAsYamlToscaFunction(String validatedPropValue, String value, UploadPropInfo propertyInfo) {
+        return StringUtils.isEmpty(validatedPropValue) && StringUtils.isNotEmpty(value) && propertyInfo.getToscaFunction() == null && CollectionUtils.isEmpty(propertyInfo.getSubPropertyToscaFunctions());
+    }
+    
+    private void addSubPropertyYamlToscaFunctions(final String validatedPropValue, final String value, final String propertyType, final UploadPropInfo propertyInfo, final Map<String, DataTypeDefinition> allDataTypes) {
+        if (StringUtils.isNotEmpty(validatedPropValue) || StringUtils.isEmpty(value) || ToscaPropertyType.isValidType(propertyType) != null) {
+            return;
+        }
+        try {
+            final JsonObject jsonObject = JsonParser.parseString(value).getAsJsonObject();
+
+            final DataTypeDefinition dataTypeDefinition = allDataTypes.get(propertyType);
+            final List<String> propertyNames =
+                    dataTypeDefinition.getProperties().stream().map(PropertyDataDefinition::getName).collect(Collectors.toList());
+
+            boolean hasSubPropertyValues = jsonObject.entrySet().stream().allMatch(entry -> propertyNames.contains(entry.getKey()));
+
+            if (hasSubPropertyValues) {
+                for (final PropertyDefinition prop : dataTypeDefinition.getProperties()) {
+                    if (propertyInfo.getSubPropertyToscaFunctions().stream()
+                            .anyMatch(subPropertyToscaFunction -> subPropertyToscaFunction.getSubPropertyPath().get(0).equals(prop.getName()))) {
+                        continue;
+                    }
+                    Optional<SubPropertyToscaFunction> subPropertyToscaFunction = createSubPropertyYamlToscaFunction(jsonObject, prop, allDataTypes);
+                    if (subPropertyToscaFunction.isPresent()) {
+                        propertyInfo.getSubPropertyToscaFunctions().add(subPropertyToscaFunction.get());
+                    }
+                }
+            }
+        } catch (Exception exception) {
+            log.info("Cannot create YAML value for {}", value);
+        }
+    }
+    
+    private Optional<SubPropertyToscaFunction> createSubPropertyYamlToscaFunction(final JsonObject jsonObject, final PropertyDefinition prop, final Map<String, DataTypeDefinition> allDataTypes) {
+        JsonElement propJsonElement = jsonObject.get(prop.getName());
+        if (propJsonElement != null) {
+            final String subPropValue = propJsonElement.toString();
+            final ComponentInstanceProperty subProperty = new ComponentInstanceProperty(prop, subPropValue, null);
+            final String validateSubPropValue =
+                    serviceBusinessLogic.validatePropValueBeforeCreate(subProperty, subPropValue, true, allDataTypes);
+
+            if (StringUtils.isEmpty(validateSubPropValue) && StringUtils.isNotEmpty(subPropValue)) {
+                try {
+                    Object yamlValue = new Yaml().loadAs(subPropValue, Object.class);
+                    SubPropertyToscaFunction subPropertyToscaFunction = new SubPropertyToscaFunction();
+                    CustomYamlFunction toscaFunction = new CustomYamlFunction();
+                    toscaFunction.setYamlValue(yamlValue);
+                    subPropertyToscaFunction.setToscaFunction(toscaFunction);
+                    subPropertyToscaFunction.setSubPropertyPath(Collections.singletonList(prop.getName()));
+                    return Optional.of(subPropertyToscaFunction);
+                } catch (Exception exception) {
+                    log.info("Cannot create YAML value for {}", subPropValue);
+                }
+            }
+        }
+        return Optional.empty();
     }
 
     protected ResponseFormat addInterfaceValuesToRi(