update dockers base version to 1.4.0
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / operations / NodeTypeOperation.java
index 1eb67e5..d9318f5 100644 (file)
@@ -1,6 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
 package org.openecomp.sdc.be.model.jsontitan.operations;
 
-import fj.data.Either;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -10,23 +39,18 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapCapabiltyProperty;
 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 import org.openecomp.sdc.be.model.ComponentParametersView;
 import org.openecomp.sdc.be.model.DerivedNodeTypeResolver;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
-import org.openecomp.sdc.be.model.RequirementDefinition;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
-import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
@@ -38,18 +62,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Qualifier;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Pattern;
+import fj.data.Either;
 
 @org.springframework.stereotype.Component("node-type-operation")
 public class NodeTypeOperation extends ToscaElementOperation {
-       public static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
-       public static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
+       public final static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
+       public final static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
 
        private static Logger log = LoggerFactory.getLogger(NodeTypeOperation.class.getName());
 
@@ -65,7 +83,10 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
                nodeType.generateUUID();
 
+               //Set missing props such as names, default lifecycle state, dates etc...
                nodeType = getResourceMetaDataFromResource(nodeType);
+
+               //Set unique ID
                String resourceUniqueId = nodeType.getUniqueId();
                if (resourceUniqueId == null) {
                        resourceUniqueId = UniqueIdBuilder.buildResourceUniqueId();
@@ -82,9 +103,11 @@ public class NodeTypeOperation extends ToscaElementOperation {
                        derivedResources = derivedResourcesResult.left().value();
                }
 
+               //Create Vertext Object and fill according to given NodeType
                GraphVertex nodeTypeVertex = new GraphVertex(VertexTypeEnum.NODE_TYPE);
                fillToscaElementVertexData(nodeTypeVertex, nodeType, JsonParseFlagEnum.ParseAll);
 
+               //Create Node Type in Graph
                Either<GraphVertex, TitanOperationStatus> createdVertex = titanDao.createVertex(nodeTypeVertex);
                if (createdVertex.isRight()) {
                        TitanOperationStatus status = createdVertex.right().value();
@@ -152,7 +175,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
        private StorageOperationStatus associateInterfacesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // Note : currently only one derived supported!!!!
-               Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, InterfaceDataDefinition.class, EdgeLabelEnum.INTERFACE_ARTIFACTS);
+               Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.INTERFACE_ARTIFACTS);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
@@ -377,7 +400,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
        }
 
        private TitanOperationStatus setResourceAttributesFromGraph(GraphVertex componentV, NodeType toscaElement) {
-               Either<Map<String, AttributeDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
+               Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
                if (result.isLeft()) {
                        toscaElement.setAttributes(result.left().value());
                } else {
@@ -413,7 +436,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
        private StorageOperationStatus addAdditionalInformationToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // Note : currently only one derived supported!!!!
-               Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, AdditionalInfoParameterDataDefinition.class, EdgeLabelEnum.ADDITIONAL_INFORMATION);
+               Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
@@ -421,7 +444,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
                Map<String, AdditionalInfoParameterDataDefinition> addInformation = nodeType.getAdditionalInformation();
                if (addInformation != null) {
-                       addInformationAll.putAll(addInformation);
+                       ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation);
                }
                if (!addInformationAll.isEmpty()) {
                        Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, addInformationAll);
@@ -434,7 +457,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
        private StorageOperationStatus associateCapabilitiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // Note : currently only one derived supported!!!!
-               Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, ListCapabilityDataDefinition.class, EdgeLabelEnum.CAPABILITIES);
+               Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
@@ -452,10 +475,28 @@ public class NodeTypeOperation extends ToscaElementOperation {
                                });
                        });
 
-                       for (Entry<String, ListCapabilityDataDefinition> entry : capabilties.entrySet()) {
-                               capabiltiesAll.merge(entry.getKey(), entry.getValue(), (list1, list2) -> list1.mergeListItemsByName(list2));
-                       }
+                       ToscaDataDefinition.mergeDataMaps(capabiltiesAll, capabilties);
+                       capabiltiesAll.values().forEach(l -> {
+                               l.getListToscaDataDefinition().forEach(c -> {
+                                       List<String> capabilitySources = c.getCapabilitySources();
+                                       if (capabilitySources == null) {
+                                               capabilitySources = new ArrayList<>();
+                                       }
+                                       capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
+                                       c.setCapabilitySources(capabilitySources);
+                               });
+                       });
                }
+               capabiltiesAll.values().forEach(l -> {
+                       l.getListToscaDataDefinition().forEach(c -> {
+                               List<String> capabilitySources = c.getCapabilitySources();
+                               if (capabilitySources == null) {
+                                       capabilitySources = new ArrayList<>();
+                               }
+                               capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
+                               c.setCapabilitySources(capabilitySources);
+                       });
+               });
                if (!capabiltiesAll.isEmpty()) {
                        Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
                        if (assosiateElementToData.isRight()) {
@@ -467,7 +508,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
        private StorageOperationStatus associateRequirementsToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // Note : currently only one derived supported!!!!
-               Either<Map<String, ListRequirementDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, ListRequirementDataDefinition.class, EdgeLabelEnum.REQUIREMENTS);
+               Either<Map<String, ListRequirementDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.REQUIREMENTS);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
@@ -484,10 +525,9 @@ public class NodeTypeOperation extends ToscaElementOperation {
                                        p.setUniqueId(uid);
                                });
                        });
-                       
-                       for (Entry<String, ListRequirementDataDefinition> entry : requirements.entrySet()) {
-                               requirementsAll.merge(entry.getKey(), entry.getValue(), (list1, list2) -> list1.mergeListItemsByName(list2));
-                       }
+
+                       ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements);
+
                }
                if (!requirementsAll.isEmpty()) {
                        Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, EdgeLabelEnum.REQUIREMENTS, requirementsAll);
@@ -500,19 +540,19 @@ public class NodeTypeOperation extends ToscaElementOperation {
 
        private StorageOperationStatus associateAttributesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // Note : currently only one derived supported!!!!
-               Either<Map<String, AttributeDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, AttributeDataDefinition.class, EdgeLabelEnum.ATTRIBUTES);
+               Either<Map<String, PropertyDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ATTRIBUTES);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
-               Map<String, AttributeDataDefinition> attributesAll = dataFromDerived.left().value();
+               Map<String, PropertyDataDefinition> attributesAll = dataFromDerived.left().value();
 
-               Map<String, AttributeDataDefinition> attributes = nodeType.getAttributes();
+               Map<String, PropertyDataDefinition> attributes = nodeType.getAttributes();
                if (attributes != null) {
                        attributes.values().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
                                String uid = UniqueIdBuilder.buildAttributeUid(nodeTypeVertex.getUniqueId(), p.getName());
                                p.setUniqueId(uid);
                        });
-                       attributesAll.putAll(attributes);
+                       ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
                }
                if (!attributesAll.isEmpty()) {
                        Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
@@ -526,7 +566,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
        // TODO get from derived
        private StorageOperationStatus associateCapabilitiesPropertiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
                // // Note : currently only one derived supported!!!!
-               Either<Map<String, MapPropertiesDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, MapPropertiesDataDefinition.class, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
+               Either<Map<String, MapPropertiesDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
@@ -542,9 +582,9 @@ public class NodeTypeOperation extends ToscaElementOperation {
                                        });
                                }
                        });
-                       propertiesAll.putAll(capabiltiesProps);
+                       ToscaDataDefinition.mergeDataMaps(propertiesAll, capabiltiesProps);
                }
-               if (propertiesAll != null) {
+               if (!propertiesAll.isEmpty()) {
                        Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, propertiesAll);
                        if (assosiateElementToData.isRight()) {
                                return assosiateElementToData.right().value();
@@ -573,11 +613,11 @@ public class NodeTypeOperation extends ToscaElementOperation {
                                                return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
                                        } else {
                                                if (resources.size() > 1) {
-                                                       log.error("Multiple parent resources called {} found in the graph.", parentResource);
-                                                       return Either.right(StorageOperationStatus.MULTIPLE_PARENT_RESOURCE_FOUND);
+                                                       return handleMultipleParent(parentResource, derivedResources, resources);
+                                               } else {
+                                                       GraphVertex parentResourceData = resources.get(0);
+                                                       derivedResources.add(parentResourceData);
                                                }
-                                               GraphVertex parentResourceData = resources.get(0);
-                                               derivedResources.add(parentResourceData);
                                        }
 
                                }
@@ -587,6 +627,44 @@ public class NodeTypeOperation extends ToscaElementOperation {
                return Either.left(derivedResources);
        }
 
+       Either<List<GraphVertex>, StorageOperationStatus> handleMultipleParent(String parentResource, List<GraphVertex> derivedResource, List<GraphVertex> fetchedDerivedResources) {
+
+               Either<List<GraphVertex>, StorageOperationStatus> result = Either.left(derivedResource);
+               try {
+                       fetchedDerivedResources.sort((d1, d2) -> {
+                               return new Double(Double.parseDouble((String) d1.getMetadataProperty(GraphPropertyEnum.VERSION))).compareTo(Double.parseDouble((String) d2.getMetadataProperty(GraphPropertyEnum.VERSION)));
+                       });
+
+                       int actualHighestIndex = fetchedDerivedResources.size() - 1;
+                       derivedResource.add(fetchedDerivedResources.get(actualHighestIndex));
+                       fetchedDerivedResources.remove(actualHighestIndex);
+
+                       StorageOperationStatus status = fixMultipleParent(fetchedDerivedResources);
+                       if (status != StorageOperationStatus.OK) {
+                               result = Either.right(status);
+                       }
+               } catch (Exception e) {
+                       CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during handle multiple parent {}. Exception is  {}", parentResource, e.getMessage());
+                       result = Either.right(StorageOperationStatus.GENERAL_ERROR);
+               }
+               return result;
+       }
+
+       private StorageOperationStatus fixMultipleParent(List<GraphVertex> fetchedDerivedResources) {
+               StorageOperationStatus result = StorageOperationStatus.OK;
+               for (GraphVertex fetchedDerivedResource : fetchedDerivedResources) {
+                       fetchedDerivedResource.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
+                       Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(fetchedDerivedResource);
+                       if (updateVertexRes.isRight()) {
+                               TitanOperationStatus titatStatus = updateVertexRes.right().value();
+                               CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version of node type {} to false. Status is  {}", fetchedDerivedResource.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME), titatStatus);
+                               result = DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus);
+                               break;
+                       }
+               }
+               return result;
+       }
+
        private GraphVertex fillMetadata(GraphVertex nodeTypeVertex, NodeType nodeType) {
                nodeTypeVertex.setLabel(VertexTypeEnum.NODE_TYPE);
 
@@ -657,7 +735,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
        protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) {
 
                NodeType nodeType = (NodeType) toscaElementToUpdate;
-               List<GraphVertex> derivedResources = null;
+               List<GraphVertex> derivedResources = new ArrayList<>();
 
                List<String> derivedFromResources = nodeType.getDerivedFrom();
 
@@ -690,75 +768,138 @@ public class NodeTypeOperation extends ToscaElementOperation {
                                        return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
                                }
                                // must be only one
-                               GraphVertex newDerived = getParentResources.left().value().get(0);
-                               StorageOperationStatus updateStatus = updateDataFromNewDerived(newDerived, nodeTypeV);
-                               if (updateStatus != StorageOperationStatus.OK) {
-                                       CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerived.getUniqueId(), updateStatus);
-                                       return updateStatus;
-                               }
-
-                               Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, firstDerivedInChain, EdgeLabelEnum.DERIVED_FROM);
-                               if (deleteEdge.isRight()) {
-                                       TitanOperationStatus deleteError = deleteEdge.right().value();
-                                       log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), firstDerivedInChain.getUniqueId(), deleteError);
-                                       return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
-                               }
-
-                               titanDao.createEdge(nodeTypeV, newDerived, EdgeLabelEnum.DERIVED_FROM, null);
+                               GraphVertex newDerivedV = getParentResources.left().value().get(0);
+                               return updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, newDerivedV, false);
                        }
                }
+               return StorageOperationStatus.OK;
+       }
+
+       /**
+        * 
+        * @param toscaElementToUpdate
+        * @param nodeTypeV
+        * @param preDerivedV
+        * @param newDerivedV
+        * @param mergeValues
+        * @return
+        */
+       protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) {
+               Set<String> preDerivedChainIdList = new HashSet();
+               preDerivedChainIdList.add(preDerivedV.getUniqueId());
+               Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(preDerivedV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
+               while (childVertex.isLeft()) {
+                       GraphVertex currentChield = childVertex.left().value();
+                       preDerivedChainIdList.add(currentChield.getUniqueId());
+                       childVertex = titanDao.getChildVertex(currentChield, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
+               }
+
+               List<GraphVertex> derivedResources = new ArrayList<>();
+               derivedResources.add(newDerivedV);
+               StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType) toscaElementToUpdate, mergeValues, preDerivedChainIdList);
+               if (updateStatus != StorageOperationStatus.OK) {
+                       CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerivedV.getUniqueId(), updateStatus);
+                       return updateStatus;
+               }
+
+               Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, preDerivedV, EdgeLabelEnum.DERIVED_FROM);
+               if (deleteEdge.isRight()) {
+                       TitanOperationStatus deleteError = deleteEdge.right().value();
+                       log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), preDerivedV.getUniqueId(), deleteError);
+                       return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
+               }
+
+               titanDao.createEdge(nodeTypeV, newDerivedV, EdgeLabelEnum.DERIVED_FROM, new HashMap<>());
 
                return StorageOperationStatus.OK;
        }
 
-       private StorageOperationStatus updateDataFromNewDerived(GraphVertex newDerived, GraphVertex nodeTypeV) {
-               StorageOperationStatus status = updateDataByType(newDerived, nodeTypeV, EdgeLabelEnum.CAPABILITIES, CapabilityDataDefinition.class);
-               if (status != StorageOperationStatus.OK) {
-                       return status;
+       private StorageOperationStatus associateDerivedDataByType(EdgeLabelEnum edgeLabel, GraphVertex nodeTypeV, NodeType nodeToUpdate, List<GraphVertex> newDerived) {
+
+               switch (edgeLabel) {
+               case CAPABILITIES:
+                       return associateCapabilitiesToResource(nodeTypeV, nodeToUpdate, newDerived);
+               case REQUIREMENTS:
+                       return associateRequirementsToResource(nodeTypeV, nodeToUpdate, newDerived);
+               case PROPERTIES:
+                       return associatePropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
+               case ATTRIBUTES:
+                       return associateAttributesToResource(nodeTypeV, nodeToUpdate, newDerived);
+               case ADDITIONAL_INFORMATION:
+                       return addAdditionalInformationToResource(nodeTypeV, nodeToUpdate, newDerived);
+               case CAPABILITIES_PROPERTIES:
+                       return associateCapabilitiesPropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
+               default:
+                       return StorageOperationStatus.OK;
                }
-               status = updateDataByType(newDerived, nodeTypeV, EdgeLabelEnum.REQUIREMENTS, RequirementDefinition.class);
-               if (status != StorageOperationStatus.OK) {
-                       return status;
-               }
-               status = updateDataByType(newDerived, nodeTypeV, EdgeLabelEnum.PROPERTIES, PropertyDataDefinition.class);
-               if (status != StorageOperationStatus.OK) {
-                       return status;
-               }
-               status = updateDataByType(newDerived, nodeTypeV, EdgeLabelEnum.ATTRIBUTES, AttributeDataDefinition.class);
-               if (status != StorageOperationStatus.OK) {
-                       return status;
+
+       }
+
+       private StorageOperationStatus updateDataFromNewDerived(List<GraphVertex> newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set<String> preDerivedChainIdList) {
+               EnumSet<EdgeLabelEnum> edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION);
+               StorageOperationStatus status = null;
+               for (EdgeLabelEnum edge : edgeLabels) {
+                       status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate, mergeValues, preDerivedChainIdList);
+                       if (status != StorageOperationStatus.OK) {
+                               break;
+                       }
                }
-               // TODO
-               // status = updateDataByType(newDerived, nodeTypeV,
-               // EdgeLabelEnum.CAPABILITIES_PROPERTIES, capa);
-               // if ( status != StorageOperationStatus.OK){
-               // return status;
-               // }
-               status = updateDataByType(newDerived, nodeTypeV, EdgeLabelEnum.ADDITIONAL_INFORMATION, AdditionalInfoParameterDataDefinition.class);
                return status;
+
        }
 
-       private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(GraphVertex newDerived, GraphVertex nodeTypeV, EdgeLabelEnum label, Class<T> clazz) {
+       private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(List<GraphVertex> newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set<String> preDerivedChainIdList) {
                log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label);
                Either<GraphVertex, TitanOperationStatus> dataFromGraph = getDataVertex(nodeTypeV, label);
                if (dataFromGraph.isRight()) {
+                       if (TitanOperationStatus.NOT_FOUND == dataFromGraph.right().value())
+                               return associateDerivedDataByType(label, nodeTypeV, nodeElement, newDerivedList);
                        return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
                }
                GraphVertex dataV = dataFromGraph.left().value();
 
                Map<String, T> mapFromGraph = (Map<String, T>) dataV.getJson();
-               mapFromGraph.entrySet().removeIf(e -> e.getValue().getOwnerId() != null);
-
-               List<GraphVertex> derivedList = new ArrayList<>();
-               derivedList.add(newDerived);
+               Map<String, T> valuesFrmPrev = null;
+               if (isSimpleHierarchy(label)) {
+                       if (mergeValues) {
+                               valuesFrmPrev = mapFromGraph.entrySet().stream().filter(e -> e.getValue().getOwnerId() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+                       }
+                       mapFromGraph.entrySet().removeIf(e -> preDerivedChainIdList.contains(e.getValue().getOwnerId()));
+               } else {
+                       final Map<String, T> valuesFrmPrevFinal = new HashMap<>();
+                       mapFromGraph.entrySet().stream().forEach(e -> {
+                               T value = e.getValue();
+                               value = ToscaDataDefinition.removeAndCollectByOwnerId(value, preDerivedChainIdList);
+                               valuesFrmPrevFinal.put(e.getKey(), value);
+                       });
+                       valuesFrmPrev = valuesFrmPrevFinal;
+                       mapFromGraph.entrySet().removeIf(e->e.getValue().isEmpty());
+               }
 
-               Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedList, clazz, EdgeLabelEnum.CAPABILITIES);
+               Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label);
                if (dataFromDerived.isRight()) {
                        return dataFromDerived.right().value();
                }
-               Map<String, T> capabiltiesAll = dataFromDerived.left().value();
-               capabiltiesAll.putAll(mapFromGraph);
-
+               Map<String, T> dataFromDerivedAll = dataFromDerived.left().value();
+
+               Either<Map<String, T>, String> merged = ToscaDataDefinition.mergeDataMaps(dataFromDerivedAll, mapFromGraph);
+               if (merged.isRight()) {
+                       log.debug("property {} cannot be overriden", merged.right().value());
+                       return StorageOperationStatus.INVALID_PROPERTY;
+               }
+               if (mergeValues && valuesFrmPrev != null) {
+                       valuesFrmPrev.entrySet().forEach(e -> {
+                               T newData = merged.left().value().get(e.getKey());
+                               if (newData != null) {
+                                       if (isSimpleHierarchy(label)) {
+                                               e.getValue().mergeFunction(newData, true);
+                                       }else{
+                                               e.getValue().updateIfExist(newData, true);
+                                       }
+                               }
+                       });
+               }
+               dataV.setJson(dataFromDerivedAll);
                Either<GraphVertex, TitanOperationStatus> updateDataV = updateOrCopyOnUpdate(dataV, nodeTypeV, label);
                if (updateDataV.isRight()) {
                        return DaoStatusConverter.convertTitanStatusToStorageStatus(updateDataV.right().value());
@@ -766,9 +907,72 @@ public class NodeTypeOperation extends ToscaElementOperation {
                return StorageOperationStatus.OK;
        }
 
+       private boolean isSimpleHierarchy(EdgeLabelEnum label) {
+               switch (label) {
+               case PROPERTIES:
+               case ATTRIBUTES:
+               case ADDITIONAL_INFORMATION:
+               case ARTIFACTS:
+               case GROUPS:
+               case INPUTS:
+                       return true;
+               default:
+                       return false;
+               }
+       }
+
        @Override
        public <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) {
                fillMetadata(elementV, (NodeType) toscaElementToUpdate);
        }
 
+       public Either<ToscaElement, StorageOperationStatus> shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) {
+               NodeType nodeType = (NodeType) toscaElementToUpdate;
+
+               Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
+               if (childVertex.isRight()) {
+                       TitanOperationStatus getchildError = childVertex.right().value();
+                       if (getchildError == TitanOperationStatus.NOT_FOUND) {
+                               log.debug("derived resource for element {} not found", nodeTypeV.getUniqueId());
+                               return Either.right(StorageOperationStatus.OK);
+                       }
+
+                       log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchildError);
+                       return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getchildError));
+               }
+               GraphVertex firstDerivedInChain = childVertex.left().value();
+
+               String currentVersion = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.VERSION);
+
+               Map<GraphPropertyEnum, Object> props = new HashMap<>();
+               props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeType.getDerivedFrom().get(0));
+               props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+               props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
+
+               Map<GraphPropertyEnum, Object> propsHasNot = new HashMap<>();
+               propsHasNot.put(GraphPropertyEnum.IS_DELETED, true);
+               Either<List<GraphVertex>, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, props, propsHasNot, JsonParseFlagEnum.NoParse);
+               if (byCriteria.isRight()) {
+                       log.debug("Failed to fetch derived by props {} error {}", props, byCriteria.right().value());
+                       return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
+               }
+               List<GraphVertex> lastDerived = byCriteria.left().value();
+               // now supported only one derived!!! Change in future!(Evg)
+               GraphVertex derivedFromHighest = lastDerived.get(0);
+               String highestVersion = (String) derivedFromHighest.getMetadataProperty(GraphPropertyEnum.VERSION);
+               if (!highestVersion.equals(currentVersion)) {
+
+                       // need to update to latest version of derived from
+                       StorageOperationStatus updateDerived = updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, derivedFromHighest, true);
+
+                       if (updateDerived != StorageOperationStatus.OK) {
+                               log.debug("Failed to update {} to highest derived {} from error {}", nodeTypeV.getUniqueId(), derivedFromHighest.getUniqueId(), updateDerived);
+                               return Either.right(updateDerived);
+                       }
+                       return getToscaElement(nodeTypeV.getUniqueId(), new ComponentParametersView());
+               }
+               // no version changes
+               return Either.right(StorageOperationStatus.OK);
+       }
+
 }