Support TOSCA functions in sub properties
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentInstanceBusinessLogic.java
index dcccfd9..684645a 100644 (file)
@@ -43,12 +43,12 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.json.JSONObject;
 import org.onap.sdc.tosca.datatypes.model.PropertyType;
 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
-import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier;
 import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier;
 import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator;
 import org.openecomp.sdc.be.components.impl.utils.DirectivesUtil;
@@ -130,6 +130,7 @@ import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
+import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
 import org.openecomp.sdc.be.user.Role;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
@@ -184,6 +185,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private CompositionBusinessLogic compositionBusinessLogic;
     @Autowired
     private ContainerInstanceTypesData containerInstanceTypesData;
+    private final ToscaFunctionValidator toscaFunctionValidator;
 
     @Autowired
     public ComponentInstanceBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation,
@@ -193,7 +195,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                                           ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL,
                                           ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator,
                                           ForwardingPathOperation forwardingPathOperation, NodeFilterOperation nodeFilterOperation,
-                                          ArtifactsOperations artifactToscaOperation) {
+                                          ArtifactsOperations artifactToscaOperation, final ToscaFunctionValidator toscaFunctionValidator) {
         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
             artifactToscaOperation);
         this.componentInstanceOperation = componentInstanceOperation;
@@ -202,6 +204,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         this.onChangeInstanceOperationOrchestrator = onChangeInstanceOperationOrchestrator;
         this.forwardingPathOperation = forwardingPathOperation;
         this.nodeFilterOperation = nodeFilterOperation;
+        this.toscaFunctionValidator = toscaFunctionValidator;
     }
 
     public ComponentInstance createComponentInstance(String containerComponentParam, String containerComponentId, String userId,
@@ -1962,14 +1965,16 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 validatePropertyExistsOnComponent(property, containerComponent, foundResourceInstance);
                 String propertyParentUniqueId = property.getParentUniqueId();
                 if (property.isToscaFunction()) {
-                    if (property.getToscaFunction().getType() == null) {
-                        throw ToscaFunctionExceptionSupplier.missingFunctionType().get();
-                    }
-                    if (property.isToscaGetFunction()) {
-                        validateToscaGetFunction(property, containerComponent);
-                    }
+                    toscaFunctionValidator.validate(property, containerComponent);
                     property.setValue(property.getToscaFunction().getValue());
                 }
+                if (CollectionUtils.isNotEmpty(property.getSubPropertyToscaFunctions())){
+                    final JSONObject jObject  = property.getValue() == null ? new JSONObject() : new JSONObject(property.getValue());
+                    property.getSubPropertyToscaFunctions().stream().forEach(subToscaFunction -> {
+                        setJsonObjectForSubProperty(jObject, subToscaFunction.getSubPropertyPath(), subToscaFunction.getToscaFunction().getValue());
+                    });
+                    property.setValue(jObject.toString());
+                }
                 Either<String, ResponseFormat> updatedPropertyValue = updatePropertyObjectValue(property, containerComponent.getModel());
                 if (updatedPropertyValue.isRight()) {
                     log.error("Failed to update property object value of property: {}",
@@ -2014,6 +2019,22 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
         }
     }
+    
+    private void setJsonObjectForSubProperty(final JSONObject jObject, final List<String> path, String value) {
+        if (path.size() == 1) {
+            if (!value.startsWith("{")) {
+                value = new StringBuilder("{").append(value).append("}").toString();
+            }
+            final JSONObject jObjectSub  = new JSONObject(value);
+            jObject.put(path.get(0), jObjectSub);
+        } else {
+            if (!jObject.has(path.get(0))) {
+                jObject.put(path.get(0), new JSONObject());
+            }
+            final JSONObject jsonObject = jObject.getJSONObject(path.get(0));
+            setJsonObjectForSubProperty(jsonObject, path.subList(1, path.size()), value);
+        }
+    }
 
     public Either<List<ComponentInstanceAttribute>, ResponseFormat> createOrUpdateAttributeValues(final ComponentTypeEnum componentTypeEnum,
                                                                                                   final String componentId,
@@ -2303,7 +2324,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // Specific Update Logic
         String newValue = property.getValue();
 
-        if (property.hasToscaFunction()) {
+        if (property.hasToscaFunction() || CollectionUtils.isNotEmpty(property.getSubPropertyToscaFunctions())) {
             return Either.left(newValue);
         }
 
@@ -2990,6 +3011,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 newComponentInstance.setInstanceCount(resResourceInfo.getInstanceCount());
                 newComponentInstance.setMaxOccurrences(resResourceInfo.getMaxOccurrences());
                 newComponentInstance.setMinOccurrences(resResourceInfo.getMinOccurrences());
+                newComponentInstance.setDirectives(resResourceInfo.getDirectives());
                 checkForExternalReqAndCapabilities(origComponent, resResourceInfo);
 
                 ComponentInstance updatedComponentInstance =
@@ -3014,6 +3036,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     log.debug("Component with id {} was not found", containerComponentId);
                     throw new ByActionStatusComponentException(actionStatus, Constants.EMPTY_STRING);
                 }
+
+                maintainNodeFilters(currentResourceInstance, newComponentInstance, containerComponentId);
+
                 resourceInstanceStatus = getResourceInstanceById(updatedComponentRes.left().value(),
                     updatedComponentInstance.getUniqueId());
                 if (resourceInstanceStatus.isRight()) {
@@ -3030,6 +3055,19 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
+    private void maintainNodeFilters(
+            ComponentInstance currentResourceInstance,
+            ComponentInstance newComponentInstance,
+            String containerComponentId) {
+        CINodeFilterDataDefinition filterToMaintain = currentResourceInstance.getNodeFilter();
+        if (null != filterToMaintain) {
+            nodeFilterOperation.addNodeFilterData(
+                    containerComponentId.toLowerCase(),
+                    newComponentInstance.getUniqueId(),
+                    filterToMaintain);
+        }
+    }
+
     private void checkForExternalReqAndCapabilities(Component component, ComponentInstance resResourceInfo) {
         Map<String, List<RequirementDefinition>> requirementsMap = resResourceInfo.getRequirements();
         Map<String, List<RequirementDefinition>> externalRequirementsMap = new HashMap<>();
@@ -3098,9 +3136,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     containerComponentId);
             }
 
-            List<ComponentInstanceProperty> instanceProperties = containerComponent.getComponentInstancesProperties().get(componentInstanceUniqueId);
-            if (CollectionUtils.isEmpty(instanceProperties)) {
-                instanceProperties = new ArrayList<>();
+            List<ComponentInstanceProperty> instanceProperties = new ArrayList<>();
+            if (MapUtils.isNotEmpty(containerComponent.getComponentInstancesProperties())) {
+                instanceProperties = containerComponent.getComponentInstancesProperties()
+                    .get(componentInstanceUniqueId);
             }
             return instanceProperties;
         } catch (ComponentException e) {