Improve test coverage
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentInstanceBusinessLogic.java
index b8fabc3..7cb9858 100644 (file)
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.openecomp.sdc.be.components.impl;
 
 import static org.openecomp.sdc.be.components.attribute.GetOutputUtils.isGetOutputValueForOutput;
@@ -41,12 +42,17 @@ import java.util.UUID;
 import java.util.stream.Collectors;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.text.StringEscapeUtils;
+import org.json.JSONArray;
+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.ToscaGetFunctionExceptionSupplier;
 import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator;
 import org.openecomp.sdc.be.components.impl.utils.DirectivesUtil;
 import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic;
@@ -60,6 +66,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
+import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
@@ -69,9 +76,12 @@ import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
+import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.PropertySource;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 import org.openecomp.sdc.be.exception.BusinessException;
@@ -97,12 +107,14 @@ import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
 import org.openecomp.sdc.be.model.OutputDefinition;
 import org.openecomp.sdc.be.model.PolicyDefinition;
+import org.openecomp.sdc.be.model.PropertyConstraint;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.RelationshipInfo;
 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
 import org.openecomp.sdc.be.model.RequirementDefinition;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.ToscaPropertyData;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
@@ -124,6 +136,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;
@@ -138,6 +151,7 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.yaml.snakeyaml.Yaml;
 
 @org.springframework.stereotype.Component
 public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
@@ -156,17 +170,27 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private static final String CREATE_OR_UPDATE_PROPERTY_VALUE = "CreateOrUpdatePropertyValue";
     private static final String FAILED_TO_COPY_COMP_INSTANCE_TO_CANVAS = "Failed to copy the component instance to the canvas";
     private static final String COPY_COMPONENT_INSTANCE_OK = "Copy component instance OK";
-    private static final String CANNOT_ATTACH_RESOURCE_INSTANCES_TO_CONTAINER_RESOURCE_OF_TYPE = "Cannot attach resource instances to container resource of type {}";
+    private static final String CANNOT_ATTACH_RESOURCE_INSTANCES_TO_CONTAINER_RESOURCE_OF_TYPE =
+        "Cannot attach resource instances to container resource of type {}";
     private static final String FAILED_TO_UPDATE_COMPONENT_INSTANCE_CAPABILITY = "Failed to update component instance capability on instance {} in "
         + "container {}";
     private static final String SERVICE_PROXY = "serviceProxy";
     private static final String ASSOCIATE_RI_TO_RI = "associateRIToRI";
-    private ComponentInstanceOperation componentInstanceOperation;
-    private ArtifactsBusinessLogic artifactBusinessLogic;
-    private ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL;
-    private ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator;
-    private ForwardingPathOperation forwardingPathOperation;
-    private NodeFilterOperation nodeFilterOperation;
+    private static final String COMPONENT_ARCHIVED = "Component is archived. Component id: {}";
+    private static final String RESTRICTED_OPERATION_ON_SERVIVE = "Restricted operation for user: {} on service {}";
+    private static final String FAILED_TO_LOCK_COMPONENT = "Failed to lock component {}";
+    private static final String RESTRICTED_OPERATION_ON_COMPONENT = "Restricted operation for user: {} on component {}";
+    private static final String RESOURCE_INSTANCE = "resource instance";
+    private static final String SERVICE = "service";
+
+    private final ComponentInstanceOperation componentInstanceOperation;
+    private final ArtifactsBusinessLogic artifactBusinessLogic;
+    private final ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL;
+    private final ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator;
+    private final ForwardingPathOperation forwardingPathOperation;
+    private final NodeFilterOperation nodeFilterOperation;
+    private final ToscaFunctionValidator toscaFunctionValidator;
+    private final PropertyBusinessLogic propertyBusinessLogic;
     @Autowired
     private CompositionBusinessLogic compositionBusinessLogic;
     @Autowired
@@ -180,7 +204,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                                           ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL,
                                           ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator,
                                           ForwardingPathOperation forwardingPathOperation, NodeFilterOperation nodeFilterOperation,
-                                          ArtifactsOperations artifactToscaOperation) {
+                                          ArtifactsOperations artifactToscaOperation, final ToscaFunctionValidator toscaFunctionValidator,
+                                          PropertyBusinessLogic propertyBusinessLogic) {
         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
             artifactToscaOperation);
         this.componentInstanceOperation = componentInstanceOperation;
@@ -189,6 +214,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         this.onChangeInstanceOperationOrchestrator = onChangeInstanceOperationOrchestrator;
         this.forwardingPathOperation = forwardingPathOperation;
         this.nodeFilterOperation = nodeFilterOperation;
+        this.toscaFunctionValidator = toscaFunctionValidator;
+        this.propertyBusinessLogic = propertyBusinessLogic;
     }
 
     public ComponentInstance createComponentInstance(String containerComponentParam, String containerComponentId, String userId,
@@ -417,7 +444,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     }
 
     private Component getOrigComponentForServiceProxy(org.openecomp.sdc.be.model.Component containerComponent, ComponentInstance resourceInstance) {
-        Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY);
+        Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY, null);
         if (isServiceProxyOrigin(serviceProxyOrigin)) {
             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value()));
         }
@@ -438,7 +465,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         final Component service = getServiceResult.left().value();
         final Either<Component, StorageOperationStatus> getServiceDerivedFromTypeResult = toscaOperationFacade
-            .getLatestByToscaResourceName(service.getDerivedFromGenericType());
+            .getLatestByToscaResourceName(service.getDerivedFromGenericType(), service.getModel());
         if (getServiceDerivedFromTypeResult.isRight()) {
             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value()));
         }
@@ -519,7 +546,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 validateInstanceName(resourceInstance);
                 if (originType == OriginTypeEnum.ServiceProxy) {
                     log.debug("enter createRealComponentInstance,originType equals ServiceProxy");
-                    Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY);
+                    Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY, null);
                     if (isServiceProxyOrigin(serviceProxyOrigin)) {
                         throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value()));
                     }
@@ -629,7 +656,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private void validateOriginComponentIsValidForContainer(Component containerComponent, ResourceTypeEnum resourceType) {
         switch (containerComponent.getComponentType()) {
             case SERVICE:
-                if (!containerInstanceTypesData.isAllowedForServiceComponent(resourceType)) {
+                if (!containerInstanceTypesData.isAllowedForServiceComponent(resourceType, containerComponent.getModel())) {
                     throw new ByActionStatusComponentException(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE,
                         containerComponent.getComponentType().toString(), resourceType.name());
                 }
@@ -907,7 +934,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     }
                     if (CollectionUtils.isNotEmpty(filteredGroups)) {
                         filteredGroups.stream()
-                            .filter(g -> g.getArtifacts().stream().anyMatch(p -> p.equals(artifactDefinition.getGeneratedFromId()))).findFirst()
+                            .filter(g -> g.getArtifacts() != null &&
+                                g.getArtifacts().stream().anyMatch(p -> p.equals(artifactDefinition.getGeneratedFromId()))).findFirst()
                             .ifPresent(g -> fillInstanceArtifactMap(groupInstancesArtifacts, artifactDefinition, g));
                     }
                 }
@@ -1255,6 +1283,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         oldComponentInstance.setModificationTime(System.currentTimeMillis());
         oldComponentInstance.setCustomizationUUID(UUID.randomUUID().toString());
         oldComponentInstance.setDirectives(newComponentInstance.getDirectives());
+        oldComponentInstance.setMaxOccurrences(newComponentInstance.getMaxOccurrences());
+        oldComponentInstance.setMinOccurrences(newComponentInstance.getMinOccurrences());
+        oldComponentInstance.setInstanceCount(newComponentInstance.getInstanceCount());
         if (oldComponentInstance.getGroupInstances() != null) {
             oldComponentInstance.getGroupInstances().forEach(group -> group.setName(getNewGroupName(oldComponentInstance.getNormalizedName(),
                 ValidationUtils.normalizeComponentInstanceName(newComponentInstance.getName()), group.getName())));
@@ -1857,43 +1888,6 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
      * @param userId
      * @return
      */
-    public Either<ComponentInstanceProperty, ResponseFormat> createOrUpdateAttributeValue(ComponentTypeEnum componentTypeEnum, String componentId,
-                                                                                          String resourceInstanceId,
-                                                                                          ComponentInstanceProperty attribute, String userId) {
-        Either<ComponentInstanceProperty, ResponseFormat> result = null;
-        Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
-        validateUserExists(userId);
-        if (errorWrapper.isEmpty()) {
-            validateComponentTypeEnum(componentTypeEnum, "CreateOrUpdateAttributeValue", errorWrapper);
-        }
-        if (errorWrapper.isEmpty()) {
-            validateCanWorkOnComponent(componentId, componentTypeEnum, userId, errorWrapper);
-        }
-        if (errorWrapper.isEmpty()) {
-            validateComponentLock(componentId, componentTypeEnum, errorWrapper);
-        }
-        try {
-            if (errorWrapper.isEmpty()) {
-                final boolean isCreate = Objects.isNull(attribute.getValueUniqueUid());
-                if (isCreate) {
-                    result = createAttributeValue(attribute, resourceInstanceId);
-                } else {
-                    result = updateAttributeValue(attribute, resourceInstanceId);
-                }
-            } else {
-                result = Either.right(errorWrapper.getInnerElement());
-            }
-            return result;
-        } finally {
-            if (result == null || result.isRight()) {
-                janusGraphDao.rollback();
-            } else {
-                janusGraphDao.commit();
-            }
-            // unlock resource
-            graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
-        }
-    }
 
     public Either<List<ComponentInstanceProperty>, ResponseFormat> createOrUpdatePropertiesValues(ComponentTypeEnum componentTypeEnum,
                                                                                                   String componentId, String resourceInstanceId,
@@ -1919,20 +1913,26 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
             if (Boolean.TRUE.equals(containerComponent.isArchived())) {
-                log.info("Component is archived. Component id: {}", componentId);
+                log.info(COMPONENT_ARCHIVED, componentId);
                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName()));
             }
-            log.info("Restricted operation for user: {} on service {}", userId, componentId);
+            log.info(RESTRICTED_OPERATION_ON_SERVIVE, userId, componentId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
 
         Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent, resourceInstanceId);
         if (resourceInstanceStatus.isRight()) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
-                resourceInstanceId, "resource instance", "service", componentId));
+                resourceInstanceId, RESOURCE_INSTANCE, SERVICE, componentId));
         }
         ComponentInstance foundResourceInstance = resourceInstanceStatus.left().value();
 
+        // Validate instance property against it's constrains
+        Either<Boolean, ResponseFormat> constraintValidatorResponse = validatePropertyValueConstraint(properties, componentId);
+        if (constraintValidatorResponse.isRight()) {
+            log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value());
+            return Either.right(constraintValidatorResponse.right().value());
+        }
         // lock resource
         StorageOperationStatus lockStatus = graphLockOperation.lockComponent(componentId, componentTypeEnum.getNodeType());
         if (lockStatus != StorageOperationStatus.OK) {
@@ -1943,10 +1943,33 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         try {
             for (ComponentInstanceProperty property : properties) {
                 validateMandatoryFields(property);
-                ComponentInstanceProperty componentInstanceProperty = validatePropertyExistsOnComponent(property, containerComponent,
-                    foundResourceInstance);
+                validatePropertyExistsOnComponent(property, containerComponent, foundResourceInstance);
+                validatePropertyConstraintsNotChanged(properties, foundResourceInstance);
                 String propertyParentUniqueId = property.getParentUniqueId();
-                Either<String, ResponseFormat> updatedPropertyValue = updatePropertyObjectValue(property, false);
+                if (property.isToscaFunction()) {
+                    toscaFunctionValidator.validate(property, containerComponent);
+                    property.setValue(StringEscapeUtils.unescapeJava(property.getToscaFunction().getValue()));
+                    if (ToscaFunctionType.GET_INPUT == property.getToscaFunction().getType()) {
+                        property.setGetInputValues(Collections.singletonList(buildGetInputValue(property)));
+                    }
+                }
+                if (CollectionUtils.isNotEmpty(property.getSubPropertyToscaFunctions())) {
+                    ToscaPropertyType type = ToscaPropertyType.isValidType(property.getType());
+                    if (ToscaPropertyType.LIST.equals(type)) {
+                        final JSONArray jsonArray = property.getValue() == null ? new JSONArray() : new JSONArray(property.getValue());
+                        property.getSubPropertyToscaFunctions().stream().forEach(subToscaFunction -> {
+                            addE(jsonArray, subToscaFunction.getSubPropertyPath(), subToscaFunction.getToscaFunction().getValue());
+                        });
+                        property.setValue(jsonArray.toString());
+                    } else {
+                        final JSONObject jObject = property.getValue() == null ? new JSONObject() : new JSONObject(property.getValue());
+                        property.getSubPropertyToscaFunctions().stream().forEach(subToscaFunction -> {
+                            addE(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: {}",
                         property);
@@ -1961,12 +1984,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                             capPropDefinition.get().getName()), Either::right);
                 } else {
                     updatedPropertyValue.bimap(
-                        updatedValue -> {
-                            componentInstanceProperty.setValue(updatedValue);
-                            return updatePropertyOnContainerComponent(property, updatedValue,
-                                containerComponent, foundResourceInstance);
-                        }, Either::right);
-                    updatedProperties.add(componentInstanceProperty);
+                        updatedValue -> updatePropertyOnContainerComponent(property, updatedValue, containerComponent, foundResourceInstance),
+                        Either::right
+                    );
+                    updatedProperties.add(property);
                 }
             }
 
@@ -1993,6 +2014,65 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
+    private GetInputValueDataDefinition buildGetInputValue(final ComponentInstanceProperty property) {
+        final GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition();
+        getInputValueDataDefinition.setPropName(property.getName());
+        getInputValueDataDefinition.setInputName(((ToscaGetFunctionDataDefinition) property.getToscaFunction()).getPropertyName());
+        getInputValueDataDefinition.setInputId(((ToscaGetFunctionDataDefinition) property.getToscaFunction()).getPropertyUniqueId());
+        return getInputValueDataDefinition;
+    }
+
+    private void addE(JSONArray jsonArray, List<String> path, String value) {
+        Object objectForPath = jsonArray.opt(Integer.parseInt(path.get(0)));
+        if (objectForPath == null) {
+            if (path.size() > 1) {
+                if (StringUtils.isNumeric(path.get(1))) {
+                    objectForPath = new JSONArray();
+                } else {
+                    objectForPath = new JSONObject();
+                }
+                jsonArray.put(Integer.parseInt(path.get(0)), objectForPath);
+            }
+        }
+
+        if (path.size() == 1) {
+            Object valueAsObject = new Yaml().loadAs(value, Object.class);
+            jsonArray.put(Integer.parseInt(path.get(0)), valueAsObject);
+        } else {
+            if (objectForPath instanceof JSONObject) {
+                addE((JSONObject) objectForPath, path.subList(1, path.size()), value);
+            } else {
+                addE((JSONArray) objectForPath, path.subList(1, path.size()), value);
+            }
+        }
+    }
+
+    private void addE(JSONObject jsonObject, List<String> path, String value) {
+
+        Object objectForPath = null;
+        if (jsonObject.has(path.get(0))) {
+            objectForPath = jsonObject.get(path.get(0));
+        } else {
+            if (path.size() > 1 && StringUtils.isNumeric(path.get(1))) {
+                objectForPath = new JSONArray();
+            } else {
+                objectForPath = new JSONObject();
+            }
+            jsonObject.put(path.get(0), objectForPath);
+        }
+
+        if (path.size() == 1) {
+            Object valueAsObject = new Yaml().loadAs(value, Object.class);
+            jsonObject.put(path.get(0), valueAsObject);
+        } else {
+            if (objectForPath instanceof JSONObject) {
+                addE((JSONObject) objectForPath, path.subList(1, path.size()), value);
+            } else {
+                addE((JSONArray) objectForPath, path.subList(1, path.size()), value);
+            }
+        }
+    }
+
     public Either<List<ComponentInstanceAttribute>, ResponseFormat> createOrUpdateAttributeValues(final ComponentTypeEnum componentTypeEnum,
                                                                                                   final String componentId,
                                                                                                   final String resourceInstanceId,
@@ -2019,10 +2099,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
             if (Boolean.TRUE.equals(containerComponent.isArchived())) {
-                log.info("Component is archived. Component id: {}", componentId);
+                log.info(COMPONENT_ARCHIVED, componentId);
                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName()));
             }
-            log.info("Restricted operation for user: {} on service {}", userId, componentId);
+            log.info(RESTRICTED_OPERATION_ON_SERVIVE, userId, componentId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
 
@@ -2030,10 +2110,26 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             resourceInstanceId);
         if (resourceInstanceStatus.isRight()) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
-                resourceInstanceId, "resource instance", "service", componentId));
+                resourceInstanceId, RESOURCE_INSTANCE, SERVICE, componentId));
         }
         final ComponentInstance foundResourceInstance = resourceInstanceStatus.left().value();
 
+        // Validate instance attributes against it's constraints
+        List<PropertyDefinition> attributesToValidate = new ArrayList<>();
+        attributes.forEach((componentInstanceAttribute) -> {
+            PropertyDefinition propertyDefinition = new PropertyDefinition();
+            propertyDefinition.setValue(componentInstanceAttribute.getValue());
+            propertyDefinition.setType(componentInstanceAttribute.getType());
+            propertyDefinition.setName(componentInstanceAttribute.getName());
+            propertyDefinition.setUniqueId(componentInstanceAttribute.getUniqueId());
+            attributesToValidate.add(propertyDefinition);
+        });
+        Either<Boolean, ResponseFormat> constraintValidatorResponse = validatePropertyValueConstraint(attributesToValidate, componentId);
+        if (constraintValidatorResponse.isRight()) {
+            log.error("Failed validation value and constraint of attribute: {}", constraintValidatorResponse.right().value());
+            return Either.right(constraintValidatorResponse.right().value());
+        }
+
         // lock resource
         final StorageOperationStatus lockStatus = graphLockOperation.lockComponent(componentId, componentTypeEnum.getNodeType());
         if (lockStatus != StorageOperationStatus.OK) {
@@ -2089,29 +2185,48 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    private ComponentInstanceProperty validatePropertyExistsOnComponent(ComponentInstanceProperty property, Component containerComponent,
-                                                                        ComponentInstance foundResourceInstance) {
+    private void validatePropertyExistsOnComponent(ComponentInstanceProperty property, Component containerComponent,
+                                                   ComponentInstance foundResourceInstance) {
         List<ComponentInstanceProperty> instanceProperties = containerComponent.getComponentInstancesProperties()
             .get(foundResourceInstance.getUniqueId());
-        Optional<ComponentInstanceProperty> instanceProperty = instanceProperties.stream().filter(p -> p.getName().equals(property.getName()))
-            .findAny();
-        if (!instanceProperty.isPresent()) {
+        final boolean hasProperty = instanceProperties.stream().anyMatch(p -> p.getName().equals(property.getName()));
+        if (!hasProperty) {
             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, property.getName());
         }
-        return instanceProperty.get();
     }
 
     private ComponentInstanceAttribute validateAttributeExistsOnComponent(final ComponentInstanceAttribute attribute,
                                                                           final Component containerComponent,
                                                                           final ComponentInstance foundResourceInstance) {
-        final List<ComponentInstanceAttribute> instanceProperties =
+        final List<ComponentInstanceAttribute> instanceAttributes =
             containerComponent.getComponentInstancesAttributes().get(foundResourceInstance.getUniqueId());
+        final List<ComponentInstanceProperty> instanceProperties =
+            containerComponent.getComponentInstancesProperties().get(foundResourceInstance.getUniqueId());
         final Optional<ComponentInstanceAttribute> instanceAttribute =
+            instanceAttributes.stream().filter(p -> p.getName().equals(attribute.getName())).findAny();
+        final Optional<ComponentInstanceProperty> instanceProperty =
             instanceProperties.stream().filter(p -> p.getName().equals(attribute.getName())).findAny();
-        if (!instanceAttribute.isPresent()) {
-            throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, attribute.getName());
+        if (instanceAttribute.isPresent()) {
+            return instanceAttribute.get();
+        }
+        if (instanceProperty.isPresent()) {
+            ComponentInstanceAttribute propAttribute = getComponentInstanceAttribute(instanceProperty.get());
+            return propAttribute;
         }
-        return instanceAttribute.get();
+        throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, attribute.getName());
+    }
+
+    private ComponentInstanceAttribute getComponentInstanceAttribute(ComponentInstanceProperty property) {
+        ComponentInstanceAttribute attribute = new ComponentInstanceAttribute();
+        attribute.setParentUniqueId(property.getParentUniqueId());
+        attribute.setName(property.getName());
+        attribute.setOwnerId(property.getOwnerId());
+        attribute.setType(property.getType());
+        attribute.setSchema(property.getSchema());
+        attribute.setUniqueId(property.getUniqueId());
+        attribute.setValue(property.getValue());
+        attribute.setDefaultValue(property.getDefaultValue());
+        return attribute;
     }
 
     private ResponseFormat updateCapabilityPropertyOnContainerComponent(ComponentInstanceProperty property,
@@ -2219,16 +2334,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     }
 
     private <T extends PropertyDefinition> Either<String, ResponseFormat> validatePropertyObjectValue(T property, String newValue, boolean isInput) {
-        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = dataTypeCache.getAll();
-        if (allDataTypesEither.isRight()) {
-            JanusGraphOperationStatus status = allDataTypesEither.right().value();
-            BeEcompErrorManager.getInstance()
-                .logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update property value on instance. Status is " + status,
-                    ErrorSeverity.ERROR);
-            return Either.right(componentsUtils
-                .getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status))));
-        }
-        Map<String, DataTypeDefinition> allDataTypes = allDataTypesEither.left().value();
+        final Map<String, DataTypeDefinition> allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, property.getModel());
         String propertyType = property.getType();
         String innerType = getInnerType(property);
 
@@ -2266,30 +2372,21 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         return false;
     }
 
-    private <T extends PropertyDefinition> Either<String, ResponseFormat> updatePropertyObjectValue(T property, boolean isInput) {
-        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = dataTypeCache.getAll();
-        if (allDataTypesEither.isRight()) {
-            JanusGraphOperationStatus status = allDataTypesEither.right().value();
-            BeEcompErrorManager.getInstance()
-                .logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update property value on instance. Status is " + status,
-                    ErrorSeverity.ERROR);
-            return Either.right(componentsUtils
-                .getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status))));
-        }
-        Map<String, DataTypeDefinition> allDataTypes = allDataTypesEither.left().value();
+    private <T extends PropertyDefinition> Either<String, ResponseFormat> updatePropertyObjectValue(T property, final String model) {
+        final Map<String, DataTypeDefinition> allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, model);
         String innerType = null;
         String propertyType = property.getType();
         ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
         log.debug("The type of the property {} is {}", property.getUniqueId(), propertyType);
 
         if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
-            SchemaDefinition def = property.getSchema();
-            if (def == null) {
+            SchemaDefinition schema = property.getSchema();
+            if (schema == null) {
                 log.debug("Schema doesn't exists for property of type {}", type);
                 return Either
                     .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE)));
             }
-            PropertyDataDefinition propDef = def.getProperty();
+            PropertyDataDefinition propDef = schema.getProperty();
             if (propDef == null) {
                 log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
                 return Either
@@ -2301,8 +2398,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // Specific Update Logic
         String newValue = property.getValue();
 
-        if (property.getToscaGetFunctionType() != null) {
-            validateToscaGetFunction(property);
+        if (property.hasToscaFunction() || CollectionUtils.isNotEmpty(property.getSubPropertyToscaFunctions())) {
             return Either.left(newValue);
         }
 
@@ -2320,28 +2416,17 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 newValue = object.toString();
             }
         }
-        if (!isInput) {
-            ImmutablePair<String, Boolean> pair = propertyOperation
-                .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true);
-            if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) {
-                BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType);
-                return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
-                    DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))));
-            }
+        ImmutablePair<String, Boolean> pair = propertyOperation
+            .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true);
+        if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) {
+            BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType);
+            return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
+                DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))));
         }
         return Either.left(newValue);
     }
 
     private <T extends AttributeDefinition> Either<String, ResponseFormat> updateAttributeObjectValue(final T attribute) {
-        final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = dataTypeCache.getAll();
-        if (allDataTypesEither.isRight()) {
-            JanusGraphOperationStatus status = allDataTypesEither.right().value();
-            BeEcompErrorManager.getInstance()
-                .logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update attribute value on instance. Status is " + status,
-                    ErrorSeverity.ERROR);
-            return Either.right(componentsUtils
-                .getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status))));
-        }
         String innerType = null;
         final String attributeType = attribute.getType();
         final ToscaPropertyType type = ToscaPropertyType.isValidType(attributeType);
@@ -2366,12 +2451,12 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // Specific Update Logic
         String newValue = attribute.getValue();
 
-        final Either<Object, Boolean> isValid = attributeOperation
-            .validateAndUpdateAttributeValue(attributeType, attribute.getValue(), true, innerType, allDataTypesEither.left().value());
+        final var isValid = attributeOperation.validateAndUpdateAttributeValue(attribute, innerType,
+            componentsUtils.getAllDataTypes(applicationDataTypeCache, attribute.getModel()));
         if (isValid.isRight()) {
             final Boolean res = isValid.right().value();
             if (!Boolean.TRUE.equals(res)) {
-                log.debug("validate and update attribute value has failed with value: {}", attribute.getValue());
+                log.debug("validate and update attribute value has failed with value: {}", newValue);
                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(
                     DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
             }
@@ -2384,29 +2469,112 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         return Either.left(newValue);
     }
 
-    private <T extends PropertyDefinition> void validateToscaGetFunction(T property) {
-        if (property.getToscaGetFunctionType() == ToscaGetFunctionType.GET_INPUT) {
-            final List<GetInputValueDataDefinition> getInputValues = property.getGetInputValues();
-            if (CollectionUtils.isEmpty(getInputValues)) {
-                log.debug("No input information provided. Cannot set get_input.");
-                throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
-            }
-            if (getInputValues.size() > 1) {
-                log.debug("More than one input provided. Cannot set get_input.");
-                throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
-            }
-            final GetInputValueDataDefinition getInputValueDataDefinition = getInputValues.get(0);
+    private <T extends PropertyDefinition> void validateGetFunction(final T property,
+                                                                    final List<? extends ToscaPropertyData> parentProperties,
+                                                                    final String model) {
+        final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
+        if (CollectionUtils.isEmpty(parentProperties)) {
+            throw ToscaGetFunctionExceptionSupplier
+                .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(),
+                    toscaGetFunction.getFunctionType()
+                ).get();
+        }
+        final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId();
+        ToscaPropertyData referredProperty = parentProperties.stream()
+            .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId()))
+            .findFirst()
+            .orElseThrow(ToscaGetFunctionExceptionSupplier
+                .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource()
+                    , toscaGetFunction.getFunctionType())
+            );
+        if (toscaGetFunction.isSubProperty()) {
+            referredProperty = findSubProperty(referredProperty, toscaGetFunction, model);
+        }
 
-            if (!property.getType().equals(getInputValueDataDefinition.getInputType())) {
-                log.debug("Input type '{}' diverges from the property type '{}'. Cannot set get_input.",
-                    getInputValueDataDefinition.getInputType(), property.getType());
-                throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
+        if (!property.getType().equals(referredProperty.getType()) && !"list".equalsIgnoreCase(referredProperty.getType())) {
+            throw ToscaGetFunctionExceptionSupplier
+                .propertyTypeDiverge(toscaGetFunction.getType(), referredProperty.getType(), property.getType()).get();
+        }
+        if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getType())
+            && !"list".equalsIgnoreCase(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) {
+            throw ToscaGetFunctionExceptionSupplier
+                .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get();
+        }
+    }
+
+    private ToscaPropertyData findSubProperty(final ToscaPropertyData referredProperty,
+                                              final ToscaGetFunctionDataDefinition toscaGetFunction,
+                                              final String model) {
+        final Map<String, DataTypeDefinition> dataTypeMap = loadDataTypes(model);
+        final List<String> propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource();
+        DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType());
+        if (dataType == null) {
+            throw ToscaGetFunctionExceptionSupplier
+                .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get();
+        }
+        ToscaPropertyData foundProperty = referredProperty;
+        for (int i = 1; i < propertyPathFromSource.size(); i++) {
+            final String currentPropertyName = propertyPathFromSource.get(i);
+            foundProperty = dataType.getProperties().stream()
+                .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst()
+                .orElseThrow(
+                    ToscaGetFunctionExceptionSupplier
+                        .propertyNotFoundOnTarget(propertyPathFromSource.subList(0, i), toscaGetFunction.getPropertySource(),
+                            toscaGetFunction.getFunctionType())
+                );
+            dataType = dataTypeMap.get(foundProperty.getType());
+            if (dataType == null) {
+                throw ToscaGetFunctionExceptionSupplier
+                    .propertyDataTypeNotFound(propertyPathFromSource.subList(0, i), foundProperty.getType(),
+                        toscaGetFunction.getFunctionType()).get();
             }
-            return;
         }
+        return foundProperty;
+    }
 
-        throw new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED,
-            "Tosca function " + property.getToscaGetFunctionType().getToscaGetFunctionName());
+    private Map<String, DataTypeDefinition> loadDataTypes(String model) {
+        final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypeEither =
+            applicationDataTypeCache.getAll(model);
+        if (dataTypeEither.isRight()) {
+            throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get();
+        }
+        return dataTypeEither.left().value();
+    }
+
+    private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) {
+        if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) {
+            throw ToscaGetFunctionExceptionSupplier
+                .targetSourceNotSupported(functionType, propertySource).get();
+        }
+        if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) {
+            throw ToscaGetFunctionExceptionSupplier
+                .targetSourceNotSupported(functionType, propertySource).get();
+        }
+    }
+
+    private void validateGetToscaFunctionAttributes(final ToscaGetFunctionDataDefinition toscaGetFunction) {
+        if (toscaGetFunction.getFunctionType() == null) {
+            throw ToscaGetFunctionExceptionSupplier.targetFunctionTypeNotFound().get();
+        }
+        if (toscaGetFunction.getPropertySource() == null) {
+            throw ToscaGetFunctionExceptionSupplier.targetPropertySourceNotFound(toscaGetFunction.getFunctionType()).get();
+        }
+        if (CollectionUtils.isEmpty(toscaGetFunction.getPropertyPathFromSource())) {
+            throw ToscaGetFunctionExceptionSupplier
+                .targetSourcePathNotFound(toscaGetFunction.getFunctionType()).get();
+        }
+        if (StringUtils.isEmpty(toscaGetFunction.getSourceName()) || StringUtils.isBlank(toscaGetFunction.getSourceName())) {
+            throw ToscaGetFunctionExceptionSupplier.sourceNameNotFound(toscaGetFunction.getPropertySource()).get();
+        }
+        if (StringUtils.isEmpty(toscaGetFunction.getSourceUniqueId()) || StringUtils.isBlank(toscaGetFunction.getSourceUniqueId())) {
+            throw ToscaGetFunctionExceptionSupplier.sourceIdNotFound(toscaGetFunction.getPropertySource()).get();
+        }
+        if (StringUtils.isEmpty(toscaGetFunction.getPropertyName()) || StringUtils.isBlank(toscaGetFunction.getPropertyName())) {
+            throw ToscaGetFunctionExceptionSupplier.propertyNameNotFound(toscaGetFunction.getPropertySource()).get();
+        }
+        if (StringUtils.isEmpty(toscaGetFunction.getPropertyUniqueId()) || StringUtils.isBlank(toscaGetFunction.getPropertyUniqueId())) {
+            throw ToscaGetFunctionExceptionSupplier.propertyIdNotFound(toscaGetFunction.getPropertySource()).get();
+        }
     }
 
     private ResponseFormat updateInputOnContainerComponent(ComponentInstanceInput input, String newValue, Component containerComponent,
@@ -2447,17 +2615,17 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
             if (Boolean.TRUE.equals(containerComponent.isArchived())) {
-                log.info("Component is archived. Component id: {}", componentId);
+                log.info(COMPONENT_ARCHIVED, componentId);
                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName()));
             }
-            log.info("Restricted operation for user: {} on service {}", userId, componentId);
+            log.info(RESTRICTED_OPERATION_ON_SERVIVE, userId, componentId);
             resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
             return resultOp;
         }
         Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent, resourceInstanceId);
         if (resourceInstanceStatus.isRight()) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
-                resourceInstanceId, "resource instance", "service", componentId));
+                resourceInstanceId, RESOURCE_INSTANCE, SERVICE, componentId));
         }
 
         ComponentInstance foundResourceInstance = resourceInstanceStatus.left().value();
@@ -2818,8 +2986,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             }
 
             Component eitherOriginComponent = getInstanceOriginNode(currentResourceInstance);
-            DataForMergeHolder dataHolder = compInstMergeDataBL
-                .saveAllDataBeforeDeleting(containerComponent, currentResourceInstance, eitherOriginComponent);
+            DataForMergeHolder dataHolder =
+                compInstMergeDataBL.saveAllDataBeforeDeleting(containerComponent, currentResourceInstance, eitherOriginComponent);
             ComponentInstance resResourceInfo = deleteComponentInstance(containerComponent, componentInstanceId,
                 containerComponentType);
 
@@ -2832,7 +3000,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 newComponentInstance.setOriginType(originType);
                 if (originType == OriginTypeEnum.ServiceProxy) {
                     Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
-                        .getLatestByName(SERVICE_PROXY);
+                        .getLatestByName(SERVICE_PROXY, null);
                     if (isServiceProxyOrigin(serviceProxyOrigin)) {
                         throw new ByActionStatusComponentException(
                             componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value()));
@@ -2854,7 +3022,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     final Component service = getServiceResult.left().value();
 
                     final Either<Component, StorageOperationStatus> getServiceDerivedFromTypeResult = toscaOperationFacade
-                        .getLatestByToscaResourceName(service.getDerivedFromGenericType());
+                        .getLatestByToscaResourceName(service.getDerivedFromGenericType(), service.getModel());
                     if (getServiceDerivedFromTypeResult.isRight()) {
                         throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value()));
                     }
@@ -2869,12 +3037,21 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 } else {
                     origComponent = getOriginComponentFromComponentInstance(newComponentInstance);
                     newComponentInstance.setName(resResourceInfo.getName());
+                    final Map<String, InterfaceDefinition> componentInterfaces = origComponent.getInterfaces();
+                    if (MapUtils.isNotEmpty(componentInterfaces)) {
+                        componentInterfaces.forEach(newComponentInstance::addInterface);
+                    }
                 }
 
                 newComponentInstance.setInvariantName(resResourceInfo.getInvariantName());
                 newComponentInstance.setPosX(resResourceInfo.getPosX());
                 newComponentInstance.setPosY(resResourceInfo.getPosY());
                 newComponentInstance.setDescription(resResourceInfo.getDescription());
+                newComponentInstance.setInstanceCount(resResourceInfo.getInstanceCount());
+                newComponentInstance.setMaxOccurrences(resResourceInfo.getMaxOccurrences());
+                newComponentInstance.setMinOccurrences(resResourceInfo.getMinOccurrences());
+                newComponentInstance.setDirectives(resResourceInfo.getDirectives());
+                checkForExternalReqAndCapabilities(origComponent, resResourceInfo);
 
                 ComponentInstance updatedComponentInstance =
                     createComponentInstanceOnGraph(containerComponent, origComponent, newComponentInstance, user);
@@ -2898,8 +3075,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     log.debug("Component with id {} was not found", containerComponentId);
                     throw new ByActionStatusComponentException(actionStatus, Constants.EMPTY_STRING);
                 }
-                resourceInstanceStatus = getResourceInstanceById(updatedComponentRes.left().value(),
-                    updatedComponentInstance.getUniqueId());
+
+                maintainNodeFilters(currentResourceInstance, newComponentInstance, containerComponentId);
+
+                resourceInstanceStatus = getResourceInstanceById(updatedComponentRes.left().value(), updatedComponentInstance.getUniqueId());
                 if (resourceInstanceStatus.isRight()) {
                     throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse
                         (resourceInstanceStatus.right().value()), updatedComponentInstance.getUniqueId());
@@ -2914,6 +3093,53 @@ 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) {
+        if (MapUtils.isNotEmpty(component.getRequirements())) {
+            component.getRequirements().entrySet().forEach(requirementsMap -> {
+                if (MapUtils.isNotEmpty(resResourceInfo.getRequirements()) &&
+                    resResourceInfo.getRequirements().containsKey(requirementsMap.getKey())) {
+                    List<RequirementDefinition> resourceReqList = resResourceInfo.getRequirements().get(requirementsMap.getKey());
+                    for (RequirementDefinition requirements : requirementsMap.getValue()) {
+                        String requirementName = requirements.getName();
+                        resourceReqList.forEach(requirementDefinition -> {
+                            if (requirementName.equals(requirementDefinition.getName()) && requirementDefinition.isExternal()) {
+                                requirements.setExternal(requirementDefinition.isExternal());
+                            }
+                        });
+                    }
+                }
+            });
+        }
+        if (MapUtils.isNotEmpty(component.getCapabilities())) {
+            component.getCapabilities().entrySet().forEach(capabilityMap -> {
+                if (MapUtils.isNotEmpty(resResourceInfo.getCapabilities()) && resResourceInfo.getCapabilities().containsKey(capabilityMap.getKey())) {
+                    List<CapabilityDefinition> resourceCapList = resResourceInfo.getCapabilities().get(capabilityMap.getKey());
+                    capabilityMap.getValue().forEach(capabilities -> {
+                        String capabilityName = capabilities.getName();
+                        for (CapabilityDefinition capDef : resourceCapList) {
+                            if (capabilityName.equals(capDef.getName()) && capDef.isExternal()) {
+                                capabilities.setExternal(capDef.isExternal());
+                            }
+                        }
+                    });
+                }
+            });
+        }
+    }
+
     private boolean isFillProxyRes(StorageOperationStatus fillProxyRes) {
         if (fillProxyRes != StorageOperationStatus.OK) {
             log.debug("Failed to fill service proxy resource data with data from service, error {}", fillProxyRes);
@@ -2946,9 +3172,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) {
@@ -3057,22 +3284,18 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         return ComponentValidations.validateNameIsUniqueInComponent(oldComponentInstance.getName(), newInstanceName, containerComponent);
     }
 
-    private Either<ComponentInstance, StorageOperationStatus> getResourceInstanceById(Component containerComponent, String instanceId) {
-        Either<ComponentInstance, StorageOperationStatus> result = Either.right(StorageOperationStatus.NOT_FOUND);
-        List<ComponentInstance> instances = containerComponent.getComponentInstances();
-        Optional<ComponentInstance> foundInstance = Optional.empty();
-        if (!CollectionUtils.isEmpty(instances)) {
-            if (result.isRight()) {
-                foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst();
-                if (!foundInstance.isPresent()) {
-                    result = Either.right(StorageOperationStatus.NOT_FOUND);
-                }
-            }
-            if (result.isRight() && foundInstance.isPresent()) {
-                result = Either.left(foundInstance.get());
-            }
+    private Either<ComponentInstance, StorageOperationStatus> getResourceInstanceById(final Component containerComponent, final String instanceId) {
+        final List<ComponentInstance> instances = containerComponent.getComponentInstances();
+        if (CollectionUtils.isEmpty(instances)) {
+            return Either.right(StorageOperationStatus.NOT_FOUND);
         }
-        return result;
+
+        final Optional<ComponentInstance> foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst();
+        if (foundInstance.isEmpty()) {
+            return Either.right(StorageOperationStatus.NOT_FOUND);
+        }
+
+        return Either.left(foundInstance.get());
     }
 
     private ComponentInstance buildComponentInstance(ComponentInstance resourceInstanceForUpdate, ComponentInstance origInstanceForUpdate) {
@@ -3201,7 +3424,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         Component containerComponent = getResourceResult.left().value();
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
-            log.info("Restricted operation for user: {} on component {}", userId, containerComponentId);
+            log.info(RESTRICTED_OPERATION_ON_COMPONENT, userId, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
         Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent,
@@ -3213,7 +3436,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // lock resource
         StorageOperationStatus lockStatus = graphLockOperation.lockComponent(containerComponentId, componentTypeEnum.getNodeType());
         if (lockStatus != StorageOperationStatus.OK) {
-            log.debug("Failed to lock component {}", containerComponentId);
+            log.debug(FAILED_TO_LOCK_COMPONENT, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus)));
         }
         try {
@@ -3261,7 +3484,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         final Component containerComponent = getResourceResult.left().value();
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
-            log.info("Restricted operation for user: {} on component {}", userId, containerComponentId);
+            log.info(RESTRICTED_OPERATION_ON_COMPONENT, userId, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
         final Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus =
@@ -3273,7 +3496,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // lock resource
         final StorageOperationStatus lockStatus = graphLockOperation.lockComponent(containerComponentId, containerComponentType.getNodeType());
         if (lockStatus != StorageOperationStatus.OK) {
-            log.debug("Failed to lock component {}", containerComponentId);
+            log.debug(FAILED_TO_LOCK_COMPONENT, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus)));
         }
         var success = false;
@@ -3326,7 +3549,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         Component containerComponent = getResourceResult.left().value();
         if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
-            log.info("Restricted operation for user: {} on component {}", userId, containerComponentId);
+            log.info(RESTRICTED_OPERATION_ON_COMPONENT, userId, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
         Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent,
@@ -3339,7 +3562,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // lock resource
         StorageOperationStatus lockStatus = graphLockOperation.lockComponent(containerComponentId, componentTypeEnum.getNodeType());
         if (lockStatus != StorageOperationStatus.OK) {
-            log.debug("Failed to lock component {}", containerComponentId);
+            log.debug(FAILED_TO_LOCK_COMPONENT, containerComponentId);
             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus)));
         }
         try {
@@ -3541,7 +3764,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     if (sourceAttributeName.equals(destAttribute.getName())) {
                         log.debug("Start to copy the attribute exists {}", sourceAttributeName);
                         sourceAttribute.setUniqueId(
-                            UniqueIdBuilder.buildResourceInstanceUniuqeId("attribute", destComponentInstanceId.split("\\.")[1], sourceAttributeName));
+                            UniqueIdBuilder.buildResourceInstanceUniqueId("attribute", destComponentInstanceId.split("\\.")[1], sourceAttributeName));
                         Either<ComponentInstanceAttribute, ResponseFormat> updateAttributeValueEither = createOrUpdateAttributeValueForCopyPaste(
                             ComponentTypeEnum.SERVICE, destComponent.getUniqueId(), destComponentInstanceId, sourceAttribute, userId);
                         if (updateAttributeValueEither.isRight()) {
@@ -3725,8 +3948,43 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
+    private void validatePropertyConstraintsNotChanged(List<ComponentInstanceProperty> newProperties, ComponentInstance originalResourceInstance) {
+        for (ComponentInstanceProperty newProperty : newProperties) {
+            Optional<PropertyDefinition> originalProperty = originalResourceInstance.getProperties().stream()
+                .filter(prop -> prop.getUniqueId().equals(newProperty.getUniqueId())).findAny();
+            if (originalProperty.isPresent()) {
+                List<PropertyConstraint> originalConstraints = originalProperty.get().getConstraints();
+                List<PropertyConstraint> newConstraints = newProperty.getConstraints();
+                if (!Objects.equals(originalConstraints, newConstraints)) {
+                    throw new ByActionStatusComponentException(ActionStatus.CANNOT_CHANGE_CONSTRAINTS);
+                }
+            } else {
+                throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, newProperty.getUniqueId());
+            }
+        }
+    }
+
+    private Either<Boolean, ResponseFormat> validatePropertyValueConstraint(List<? extends PropertyDefinition> properties, final String componentId) {
+        try {
+            String propertyModel = propertyBusinessLogic.getComponentModelByComponentId(componentId);
+            PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = new PropertyValueConstraintValidationUtil();
+            return propertyValueConstraintValidationUtil.validatePropertyConstraints(properties, applicationDataTypeCache, propertyModel);
+        } catch (BusinessLogicException e) {
+            return Either.right(e.getResponseFormat());
+        }
+    }
+
     public void validateUser(final String userId) {
         final User user = userValidations.validateUserExists(userId);
         userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN));
     }
+
+    public void setCompositionBusinessLogic(CompositionBusinessLogic compositionBusinessLogic) {
+        this.compositionBusinessLogic = compositionBusinessLogic;
+    }
+
+    public void setContainerInstanceTypesData(ContainerInstanceTypesData containerInstanceTypesData) {
+        this.containerInstanceTypesData = containerInstanceTypesData;
+    }
+
 }