X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-model%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fmodel%2Fjsontitan%2Foperations%2FNodeTypeOperation.java;h=d9318f5510ad0205b55e10982cc3620c4ef9f705;hb=b96e0da8bae19842b4eab733885775cdbfbf59fa;hp=1eb67e5c512bf8e16b74d6e70e408a538db3fcc2;hpb=ed64b5edff15e702493df21aa3230b81593e6133;p=sdc.git diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java index 1eb67e5c51..d9318f5510 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java @@ -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 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 derivedResources) { // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, InterfaceDataDefinition.class, EdgeLabelEnum.INTERFACE_ARTIFACTS); + Either, 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, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES); + Either, 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 derivedResources) { // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, AdditionalInfoParameterDataDefinition.class, EdgeLabelEnum.ADDITIONAL_INFORMATION); + Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION); if (dataFromDerived.isRight()) { return dataFromDerived.right().value(); } @@ -421,7 +444,7 @@ public class NodeTypeOperation extends ToscaElementOperation { Map addInformation = nodeType.getAdditionalInformation(); if (addInformation != null) { - addInformationAll.putAll(addInformation); + ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation); } if (!addInformationAll.isEmpty()) { Either 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 derivedResources) { // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, ListCapabilityDataDefinition.class, EdgeLabelEnum.CAPABILITIES); + Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES); if (dataFromDerived.isRight()) { return dataFromDerived.right().value(); } @@ -452,10 +475,28 @@ public class NodeTypeOperation extends ToscaElementOperation { }); }); - for (Entry 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 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 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 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 derivedResources) { // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, ListRequirementDataDefinition.class, EdgeLabelEnum.REQUIREMENTS); + Either, 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 entry : requirements.entrySet()) { - requirementsAll.merge(entry.getKey(), entry.getValue(), (list1, list2) -> list1.mergeListItemsByName(list2)); - } + + ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements); + } if (!requirementsAll.isEmpty()) { Either 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 derivedResources) { // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, AttributeDataDefinition.class, EdgeLabelEnum.ATTRIBUTES); + Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ATTRIBUTES); if (dataFromDerived.isRight()) { return dataFromDerived.right().value(); } - Map attributesAll = dataFromDerived.left().value(); + Map attributesAll = dataFromDerived.left().value(); - Map attributes = nodeType.getAttributes(); + Map 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 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 derivedResources) { // // Note : currently only one derived supported!!!! - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, MapPropertiesDataDefinition.class, EdgeLabelEnum.CAPABILITIES_PROPERTIES); + Either, 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 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, StorageOperationStatus> handleMultipleParent(String parentResource, List derivedResource, List fetchedDerivedResources) { + + Either, 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 fetchedDerivedResources) { + StorageOperationStatus result = StorageOperationStatus.OK; + for (GraphVertex fetchedDerivedResource : fetchedDerivedResources) { + fetchedDerivedResource.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false); + Either 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 StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) { NodeType nodeType = (NodeType) toscaElementToUpdate; - List derivedResources = null; + List derivedResources = new ArrayList<>(); List 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 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 StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) { + Set preDerivedChainIdList = new HashSet(); + preDerivedChainIdList.add(preDerivedV.getUniqueId()); + Either 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 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 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 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 newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set preDerivedChainIdList) { + EnumSet 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 StorageOperationStatus updateDataByType(GraphVertex newDerived, GraphVertex nodeTypeV, EdgeLabelEnum label, Class clazz) { + private StorageOperationStatus updateDataByType(List newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set preDerivedChainIdList) { log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label); Either 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 mapFromGraph = (Map) dataV.getJson(); - mapFromGraph.entrySet().removeIf(e -> e.getValue().getOwnerId() != null); - - List derivedList = new ArrayList<>(); - derivedList.add(newDerived); + Map 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 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, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedList, clazz, EdgeLabelEnum.CAPABILITIES); + Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label); if (dataFromDerived.isRight()) { return dataFromDerived.right().value(); } - Map capabiltiesAll = dataFromDerived.left().value(); - capabiltiesAll.putAll(mapFromGraph); - + Map dataFromDerivedAll = dataFromDerived.left().value(); + + Either, 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 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 void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) { fillMetadata(elementV, (NodeType) toscaElementToUpdate); } + public Either shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) { + NodeType nodeType = (NodeType) toscaElementToUpdate; + + Either 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 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 propsHasNot = new HashMap<>(); + propsHasNot.put(GraphPropertyEnum.IS_DELETED, true); + Either, 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 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); + } + }