Fix bugs in attribute outputs page
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentInstanceBusinessLogic.java
index 7ea00b1..ddbc5dc 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;
@@ -43,6 +44,9 @@ 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.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;
@@ -62,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;
@@ -71,6 +76,7 @@ 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;
@@ -101,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;
@@ -128,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;
@@ -142,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 {
@@ -160,7 +170,8 @@ 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";
@@ -178,6 +189,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     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
@@ -191,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;
@@ -200,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,
@@ -918,7 +934,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                     }
                     if (CollectionUtils.isNotEmpty(filteredGroups)) {
                         filteredGroups.stream()
-                            .filter(g -> g.getArtifacts() != null && 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));
                     }
                 }
@@ -1947,6 +1964,12 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         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) {
@@ -1957,12 +1980,31 @@ 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();
-                if (property.isGetFunction()) {
-                    validateToscaGetFunction(property, containerComponent);
-                    property.setValue(property.getToscaGetFunction().generatePropertyValue());
+                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()) {
@@ -1979,12 +2021,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);
                 }
             }
 
@@ -2011,6 +2051,78 @@ 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);
+            }
+        }
+    }
+
+    private void setJsonObjectForSubProperty(final JSONObject jObject, final List<String> path, String value) {
+        if (path.size() == 1) {
+            Object valueAsObject = new Yaml().loadAs(value, Object.class);
+            jObject.put(path.get(0), valueAsObject);
+        } 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,
                                                                                                   final String resourceInstanceId,
@@ -2052,6 +2164,22 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
         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) {
@@ -2107,29 +2235,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.isEmpty()) {
+        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();
         }
-        return instanceAttribute.get();
+        if (instanceProperty.isPresent()) {
+            ComponentInstanceAttribute propAttribute = getComponentInstanceAttribute(instanceProperty.get());
+            return propAttribute;
+        }
+        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,
@@ -2301,7 +2448,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         // Specific Update Logic
         String newValue = property.getValue();
 
-        if (property.hasGetFunction()) {
+        if (property.hasToscaFunction() || CollectionUtils.isNotEmpty(property.getSubPropertyToscaFunctions())) {
             return Either.left(newValue);
         }
 
@@ -2373,7 +2520,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     }
 
     private <T extends PropertyDefinition> void validateToscaGetFunction(T property, Component parentComponent) {
-        final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction();
+        final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
+        validateGetToscaFunctionAttributes(toscaGetFunction);
         validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource());
         if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) {
             validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel());
@@ -2391,14 +2539,26 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
             return;
         }
+        if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_ATTRIBUTE) {
+            if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
+                validateGetFunction(property, parentComponent.getAttributes(), parentComponent.getModel());
+            } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
+                final ComponentInstance componentInstance =
+                    parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
+                        .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
+                validateGetFunction(property, componentInstance.getAttributes(), parentComponent.getModel());
+            }
+
+            return;
+        }
 
         throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get();
     }
 
-    private <T extends PropertyDefinition, U extends PropertyDefinition> void validateGetFunction(final T property,
-                                                                                                  final List<U> parentProperties,
-                                                                                                  final String model) {
-        final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction();
+    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(),
@@ -2406,7 +2566,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 ).get();
         }
         final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId();
-        T referredProperty = (T) parentProperties.stream()
+        ToscaPropertyData referredProperty = parentProperties.stream()
             .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId()))
             .findFirst()
             .orElseThrow(ToscaGetFunctionExceptionSupplier
@@ -2417,18 +2577,20 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             referredProperty = findSubProperty(referredProperty, toscaGetFunction, model);
         }
 
-        if (!property.getType().equals(referredProperty.getType())) {
+        if (!property.getType().equals(referredProperty.getType()) && !"list".equalsIgnoreCase(referredProperty.getType())) {
             throw ToscaGetFunctionExceptionSupplier
-                .propertyTypeDiverge(toscaGetFunction.getFunctionType(), referredProperty.getType(), property.getType()).get();
+                .propertyTypeDiverge(toscaGetFunction.getType(), referredProperty.getType(), property.getType()).get();
         }
-        if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) {
+        if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getType())
+            && !"list".equalsIgnoreCase(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) {
             throw ToscaGetFunctionExceptionSupplier
-                .propertySchemaDiverge(toscaGetFunction.getFunctionType(), referredProperty.getSchemaType(), property.getSchemaType()).get();
+                .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get();
         }
     }
 
-    private <T extends PropertyDefinition> T findSubProperty(final T referredProperty, final ToscaGetFunctionDataDefinition toscaGetFunction,
-                                                             final String model) {
+    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());
@@ -2436,10 +2598,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             throw ToscaGetFunctionExceptionSupplier
                 .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get();
         }
-        T foundProperty = referredProperty;
+        ToscaPropertyData foundProperty = referredProperty;
         for (int i = 1; i < propertyPathFromSource.size(); i++) {
             final String currentPropertyName = propertyPathFromSource.get(i);
-            foundProperty = (T) dataType.getProperties().stream()
+            foundProperty = dataType.getProperties().stream()
                 .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst()
                 .orElseThrow(
                     ToscaGetFunctionExceptionSupplier
@@ -2476,6 +2638,31 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
+    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,
                                                            ComponentInstance foundResourceInstance) {
         StorageOperationStatus status;
@@ -2885,8 +3072,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);
 
@@ -2936,13 +3123,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 } else {
                     origComponent = getOriginComponentFromComponentInstance(newComponentInstance);
                     newComponentInstance.setName(resResourceInfo.getName());
-                    final Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade
-                            .getToscaFullElement(newComponentInstance.getComponentUid());
-                    if (getComponentRes.isRight()) {
-                        throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getComponentRes.right().value()));
-                    }
-                    final Component component = getComponentRes.left().value();
-                    final Map<String, InterfaceDefinition> componentInterfaces = component.getInterfaces();
+                    final Map<String, InterfaceDefinition> componentInterfaces = origComponent.getInterfaces();
                     if (MapUtils.isNotEmpty(componentInterfaces)) {
                         componentInterfaces.forEach(newComponentInstance::addInterface);
                     }
@@ -2955,6 +3136,8 @@ 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 =
                     createComponentInstanceOnGraph(containerComponent, origComponent, newComponentInstance, user);
@@ -2978,8 +3161,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());
@@ -2994,6 +3179,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);
@@ -3026,9 +3258,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) {
@@ -3617,7 +3850,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()) {
@@ -3801,6 +4034,32 @@ 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));