2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.model.jsontitan.operations;
23 import fj.data.Either;
24 import org.apache.tinkerpop.gremlin.structure.Direction;
25 import org.apache.tinkerpop.gremlin.structure.Edge;
26 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
27 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
28 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
29 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
30 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
31 import org.openecomp.sdc.be.datatypes.elements.*;
32 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
33 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
34 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
35 import org.openecomp.sdc.be.model.ComponentParametersView;
36 import org.openecomp.sdc.be.model.DerivedNodeTypeResolver;
37 import org.openecomp.sdc.be.model.LifecycleStateEnum;
38 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
39 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
40 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
43 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
44 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
45 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
46 import org.openecomp.sdc.common.log.wrappers.Logger;
47 import org.springframework.beans.factory.annotation.Qualifier;
50 import java.util.regex.Pattern;
51 import java.util.stream.Collectors;
53 @org.springframework.stereotype.Component("node-type-operation")
54 public class NodeTypeOperation extends ToscaElementOperation {
55 public final static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
56 public final static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
57 private static final Logger log = Logger.getLogger(NodeTypeOperation.class);
58 private DerivedNodeTypeResolver derivedResourceResolver;
61 public NodeTypeOperation(@Qualifier("derived-resource-resolver") DerivedNodeTypeResolver derivedNodeTypeResolver) {
62 this.derivedResourceResolver = derivedNodeTypeResolver;
65 public Either<NodeType, StorageOperationStatus> createNodeType(NodeType nodeType) {
67 Either<NodeType, StorageOperationStatus> result = null;
69 nodeType.generateUUID();
71 //Set missing props such as names, default lifecycle state, dates etc...
72 nodeType = getResourceMetaDataFromResource(nodeType);
75 String resourceUniqueId = nodeType.getUniqueId();
76 if (resourceUniqueId == null) {
77 resourceUniqueId = UniqueIdBuilder.buildResourceUniqueId();
78 nodeType.setUniqueId(resourceUniqueId);
81 // get derived from resources
82 List<GraphVertex> derivedResources = null;
83 Either<List<GraphVertex>, StorageOperationStatus> derivedResourcesResult = findDerivedResources(nodeType);
84 if (derivedResourcesResult.isRight()) {
85 result = Either.right(derivedResourcesResult.right().value());
88 derivedResources = derivedResourcesResult.left().value();
91 //Create Vertext Object and fill according to given NodeType
92 GraphVertex nodeTypeVertex = new GraphVertex(VertexTypeEnum.NODE_TYPE);
93 fillToscaElementVertexData(nodeTypeVertex, nodeType, JsonParseFlagEnum.ParseAll);
95 //Create Node Type in Graph
96 Either<GraphVertex, TitanOperationStatus> createdVertex = titanDao.createVertex(nodeTypeVertex);
97 if (createdVertex.isRight()) {
98 TitanOperationStatus status = createdVertex.right().value();
99 log.error("Error returned after creating resource data node {}. status returned is ", nodeTypeVertex, status);
100 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
103 nodeTypeVertex = createdVertex.left().value();
105 StorageOperationStatus assosiateCommon = assosiateCommonForToscaElement(nodeTypeVertex, nodeType, derivedResources);
106 if (assosiateCommon != StorageOperationStatus.OK) {
107 result = Either.right(assosiateCommon);
111 StorageOperationStatus associateDerived = assosiateToDerived(nodeTypeVertex, derivedResources);
112 if (associateDerived != StorageOperationStatus.OK) {
113 result = Either.right(associateDerived);
116 StorageOperationStatus associateCategory = assosiateResourceMetadataToCategory(nodeTypeVertex, nodeType);
117 if (associateCategory != StorageOperationStatus.OK) {
118 result = Either.right(associateCategory);
122 StorageOperationStatus associateAttributes = associateAttributesToResource(nodeTypeVertex, nodeType, derivedResources);
123 if (associateAttributes != StorageOperationStatus.OK) {
124 result = Either.right(associateAttributes);
128 StorageOperationStatus associateRequirements = associateRequirementsToResource(nodeTypeVertex, nodeType, derivedResources);
129 if (associateRequirements != StorageOperationStatus.OK) {
130 result = Either.right(associateRequirements);
134 StorageOperationStatus associateCapabilities = associateCapabilitiesToResource(nodeTypeVertex, nodeType, derivedResources);
135 if (associateCapabilities != StorageOperationStatus.OK) {
136 result = Either.right(associateCapabilities);
139 StorageOperationStatus associateCapabilitiesProps = associateCapabilitiesPropertiesToResource(nodeTypeVertex, nodeType, derivedResources);
140 if (associateCapabilitiesProps != StorageOperationStatus.OK) {
141 result = Either.right(associateCapabilitiesProps);
145 StorageOperationStatus associateInterfaces = associateInterfacesToResource(nodeTypeVertex, nodeType, derivedResources);
146 if (associateInterfaces != StorageOperationStatus.OK) {
147 result = Either.right(associateInterfaces);
151 StorageOperationStatus addAdditionalInformation = addAdditionalInformationToResource(nodeTypeVertex, nodeType, derivedResources);
152 if (addAdditionalInformation != StorageOperationStatus.OK) {
153 result = Either.right(addAdditionalInformation);
156 result = Either.left(nodeType);
161 private StorageOperationStatus associateInterfacesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
162 // Note : currently only one derived supported!!!!
163 Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.INTERFACE_ARTIFACTS);
164 if (dataFromDerived.isRight()) {
165 return dataFromDerived.right().value();
167 Map<String, InterfaceDataDefinition> interfacArtsAll = dataFromDerived.left().value();
169 Map<String, InterfaceDataDefinition> interfacArts = nodeType.getInterfaceArtifacts();
170 if (interfacArts != null) {
171 interfacArtsAll.putAll(interfacArts);
173 if (!interfacArtsAll.isEmpty()) {
174 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.INTERFACE_ARTIFACTS, EdgeLabelEnum.INTERFACE_ARTIFACTS, interfacArtsAll);
175 if (assosiateElementToData.isRight()) {
176 return assosiateElementToData.right().value();
179 return StorageOperationStatus.OK;
183 public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId, ComponentParametersView componentParametersView) {
185 Either<GraphVertex, StorageOperationStatus> componentByLabelAndId = getComponentByLabelAndId(uniqueId, ToscaElementTypeEnum.NODE_TYPE, JsonParseFlagEnum.ParseMetadata);
186 if (componentByLabelAndId.isRight()) {
187 return Either.right(componentByLabelAndId.right().value());
189 GraphVertex componentV = componentByLabelAndId.left().value();
191 return getToscaElement(componentV, componentParametersView);
195 // -------------------------------------------------------------
197 public Either<ToscaElement, StorageOperationStatus> getToscaElement(GraphVertex componentV, ComponentParametersView componentParametersView) {
198 NodeType toscaElement;
199 toscaElement = convertToComponent(componentV);
200 TitanOperationStatus status = null;
201 if (!componentParametersView.isIgnoreUsers()) {
202 status = setCreatorFromGraph(componentV, toscaElement);
203 if (status != TitanOperationStatus.OK) {
204 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
207 status = setLastModifierFromGraph(componentV, toscaElement);
208 if (status != TitanOperationStatus.OK) {
209 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
213 if (!componentParametersView.isIgnoreProperties()) {
214 status = setResourcePropertiesFromGraph(componentV, toscaElement);
215 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
216 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
220 if (!componentParametersView.isIgnoreAttributesFrom()) {
221 status = setResourceAttributesFromGraph(componentV, toscaElement);
222 if (status != TitanOperationStatus.OK) {
223 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
227 if (!componentParametersView.isIgnoreDerivedFrom()) {
228 status = setResourceDerivedFromGraph(componentV, toscaElement);
229 if (status != TitanOperationStatus.OK) {
230 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
234 if (!componentParametersView.isIgnoreCategories()) {
235 status = setResourceCategoryFromGraph(componentV, toscaElement);
236 if (status != TitanOperationStatus.OK) {
237 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
240 if (!componentParametersView.isIgnoreRequirements()) {
241 status = setResourceRequirementsFromGraph(componentV, toscaElement);
242 if (status != TitanOperationStatus.OK) {
243 log.error("Failed to set requirement of resource {}. status is {}", componentV.getUniqueId(), status);
244 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
247 if (!componentParametersView.isIgnoreCapabilities()) {
248 status = setResourceCapabilitiesFromGraph(componentV, toscaElement);
249 if (status != TitanOperationStatus.OK) {
250 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
254 if (!componentParametersView.isIgnoreArtifacts()) {
255 status = setArtifactsFromGraph(componentV, toscaElement);
256 if (status != TitanOperationStatus.OK) {
257 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
260 if (!componentParametersView.isIgnoreAdditionalInformation()) {
261 status = setAdditionalInformationFromGraph(componentV, toscaElement);
262 if (status != TitanOperationStatus.OK) {
263 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
266 if (!componentParametersView.isIgnoreInterfaces()) {
267 status = setInterfacesFromGraph(componentV, toscaElement);
268 if (status != TitanOperationStatus.OK) {
269 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
272 if (!componentParametersView.isIgnoreAllVersions()) {
273 status = setAllVersions(componentV, toscaElement);
274 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
275 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
279 if (!componentParametersView.isIgnoreCapabiltyProperties()) {
280 status = setComponentCapPropertiesFromGraph(componentV, toscaElement);
281 if (status != TitanOperationStatus.OK) {
282 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
286 return Either.left(toscaElement);
289 private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
290 Either<Map<String, MapPropertiesDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
291 if (result.isLeft()) {
292 toscaElement.setCapabilitiesProperties(result.left().value());
294 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
295 return result.right().value();
298 return TitanOperationStatus.OK;
301 private TitanOperationStatus setInterfacesFromGraph(GraphVertex componentV, NodeType toscaElement) {
302 Either<Map<String, InterfaceDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.INTERFACE_ARTIFACTS);
303 if (result.isLeft()) {
304 toscaElement.setInterfaceArtifacts(result.left().value());
306 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
307 return result.right().value();
310 return TitanOperationStatus.OK;
313 protected <T extends ToscaElement> TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement) {
314 return setResourceCapabilitiesFromGraph(componentV, (NodeType) toscaElement);
317 private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
318 Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
319 if (result.isLeft()) {
320 toscaElement.setCapabilities(result.left().value());
322 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
323 return result.right().value();
326 return TitanOperationStatus.OK;
329 private TitanOperationStatus setResourceDerivedFromGraph(GraphVertex componentV, NodeType toscaElement) {
330 List<String> derivedFromList = new ArrayList<>();
332 TitanOperationStatus listFromGraphStatus = findResourcesPathRecursively(componentV, derivedFromList);
333 if (TitanOperationStatus.OK != listFromGraphStatus) {
334 return listFromGraphStatus;
337 if (!derivedFromList.isEmpty()) {
338 if (derivedFromList.size() > 1) {
339 List<String> lastDerivedFrom = new ArrayList<>();
340 lastDerivedFrom.add(derivedFromList.get(1));
341 toscaElement.setDerivedFrom(lastDerivedFrom);
342 toscaElement.setDerivedList(derivedFromList);
344 toscaElement.setDerivedFrom(null);
345 toscaElement.setDerivedList(derivedFromList);
349 return TitanOperationStatus.OK;
352 protected TitanOperationStatus findResourcesPathRecursively(GraphVertex nodeTypeV, List<String> resourcesPathList) {
353 Either<GraphVertex, TitanOperationStatus> parentResourceRes = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
354 resourcesPathList.add((String) nodeTypeV.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
355 while (parentResourceRes.isLeft()) {
357 GraphVertex parent = parentResourceRes.left().value();
358 resourcesPathList.add((String) parent.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
359 parentResourceRes = titanDao.getChildVertex(parent, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
361 TitanOperationStatus operationStatus = parentResourceRes.right().value();
363 if (operationStatus != TitanOperationStatus.NOT_FOUND) {
364 return operationStatus;
366 return TitanOperationStatus.OK;
371 protected <T extends ToscaElement> TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) {
372 return setResourceRequirementsFromGraph(componentV, (NodeType) toscaElement);
375 private TitanOperationStatus setResourceRequirementsFromGraph(GraphVertex componentV, NodeType toscaElement) {
376 Either<Map<String, ListRequirementDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS);
377 if (result.isLeft()) {
378 toscaElement.setRequirements(result.left().value());
380 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
381 return result.right().value();
384 return TitanOperationStatus.OK;
387 private TitanOperationStatus setResourceAttributesFromGraph(GraphVertex componentV, NodeType toscaElement) {
388 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
389 if (result.isLeft()) {
390 toscaElement.setAttributes(result.left().value());
392 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
393 return result.right().value();
396 return TitanOperationStatus.OK;
399 private TitanOperationStatus setResourcePropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
400 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.PROPERTIES);
401 if (result.isLeft()) {
402 toscaElement.setProperties(result.left().value());
404 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
405 return result.right().value();
408 return TitanOperationStatus.OK;
411 private StorageOperationStatus assosiateToDerived(GraphVertex nodeTypeVertex, List<GraphVertex> derivedResources) {
412 for (GraphVertex derivedV : derivedResources) {
413 TitanOperationStatus createEdge = titanDao.createEdge(nodeTypeVertex, derivedV, EdgeLabelEnum.DERIVED_FROM, null);
414 if (createEdge != TitanOperationStatus.OK) {
415 log.trace("Failed to associate resource {} to derived with id {}", nodeTypeVertex.getUniqueId(), derivedV.getUniqueId());
416 return DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge);
419 return StorageOperationStatus.OK;
422 private StorageOperationStatus addAdditionalInformationToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
423 // Note : currently only one derived supported!!!!
424 Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION);
425 if (dataFromDerived.isRight()) {
426 return dataFromDerived.right().value();
428 Map<String, AdditionalInfoParameterDataDefinition> addInformationAll = dataFromDerived.left().value();
430 Map<String, AdditionalInfoParameterDataDefinition> addInformation = nodeType.getAdditionalInformation();
431 if (addInformation != null) {
432 ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation);
434 if (!addInformationAll.isEmpty()) {
435 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, addInformationAll);
436 if (assosiateElementToData.isRight()) {
437 return assosiateElementToData.right().value();
440 return StorageOperationStatus.OK;
443 private StorageOperationStatus associateCapabilitiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
444 // Note : currently only one derived supported!!!!
445 Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES);
446 if (dataFromDerived.isRight()) {
447 return dataFromDerived.right().value();
449 Map<String, ListCapabilityDataDefinition> capabiltiesAll = dataFromDerived.left().value();
451 Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilities();
452 if (capabilties != null) {
453 if (capabiltiesAll == null) {
454 capabiltiesAll = new HashMap<>();
456 capabilties.values().forEach(l -> {
457 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
458 String uid = UniqueIdBuilder.buildCapabilityUid(nodeTypeVertex.getUniqueId(), p.getName());
463 ToscaDataDefinition.mergeDataMaps(capabiltiesAll, capabilties);
464 capabiltiesAll.values().forEach(l -> {
465 l.getListToscaDataDefinition().forEach(c -> {
466 List<String> capabilitySources = c.getCapabilitySources();
467 if (capabilitySources == null) {
468 capabilitySources = new ArrayList<>();
470 capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
471 c.setCapabilitySources(capabilitySources);
475 capabiltiesAll.values().forEach(l -> {
476 l.getListToscaDataDefinition().forEach(c -> {
477 List<String> capabilitySources = c.getCapabilitySources();
478 if (capabilitySources == null) {
479 capabilitySources = new ArrayList<>();
481 capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
482 c.setCapabilitySources(capabilitySources);
485 if (!capabiltiesAll.isEmpty()) {
486 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
487 if (assosiateElementToData.isRight()) {
488 return assosiateElementToData.right().value();
491 return StorageOperationStatus.OK;
494 private StorageOperationStatus associateRequirementsToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
495 // Note : currently only one derived supported!!!!
496 Either<Map<String, ListRequirementDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.REQUIREMENTS);
497 if (dataFromDerived.isRight()) {
498 return dataFromDerived.right().value();
500 Map<String, ListRequirementDataDefinition> requirementsAll = dataFromDerived.left().value();
502 Map<String, ListRequirementDataDefinition> requirements = nodeType.getRequirements();
503 if (requirements != null) {
504 if (requirementsAll == null) {
505 requirementsAll = new HashMap<>();
507 requirements.values().forEach(l -> {
508 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
509 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
514 ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements);
517 if (!requirementsAll.isEmpty()) {
518 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, EdgeLabelEnum.REQUIREMENTS, requirementsAll);
519 if (assosiateElementToData.isRight()) {
520 return assosiateElementToData.right().value();
523 return StorageOperationStatus.OK;
526 private StorageOperationStatus associateAttributesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
527 // Note : currently only one derived supported!!!!
528 Either<Map<String, PropertyDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ATTRIBUTES);
529 if (dataFromDerived.isRight()) {
530 return dataFromDerived.right().value();
532 Map<String, PropertyDataDefinition> attributesAll = dataFromDerived.left().value();
534 Map<String, PropertyDataDefinition> attributes = nodeType.getAttributes();
535 if (attributes != null) {
536 attributes.values().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
537 String uid = UniqueIdBuilder.buildAttributeUid(nodeTypeVertex.getUniqueId(), p.getName());
540 ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
542 if (!attributesAll.isEmpty()) {
543 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
544 if (assosiateElementToData.isRight()) {
545 return assosiateElementToData.right().value();
548 return StorageOperationStatus.OK;
551 // TODO get from derived
552 private StorageOperationStatus associateCapabilitiesPropertiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
553 // // Note : currently only one derived supported!!!!
554 Either<Map<String, MapPropertiesDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
555 if (dataFromDerived.isRight()) {
556 return dataFromDerived.right().value();
558 Map<String, MapPropertiesDataDefinition> propertiesAll = dataFromDerived.left().value();
559 Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabilitiesProperties();
560 if (capabiltiesProps != null) {
561 capabiltiesProps.values().forEach(l -> {
562 if (l.getMapToscaDataDefinition() != null && l.getMapToscaDataDefinition().values() != null) {
563 Collection<PropertyDataDefinition> mapToscaDataDefinition = l.getMapToscaDataDefinition().values();
564 mapToscaDataDefinition.stream().filter(p -> p != null && p.getUniqueId() == null).forEach(p -> {
565 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
570 ToscaDataDefinition.mergeDataMaps(propertiesAll, capabiltiesProps);
572 if (!propertiesAll.isEmpty()) {
573 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, propertiesAll);
574 if (assosiateElementToData.isRight()) {
575 return assosiateElementToData.right().value();
578 return StorageOperationStatus.OK;
581 public Either<List<GraphVertex>, StorageOperationStatus> findDerivedResources(NodeType nodeType) {
583 List<GraphVertex> derivedResources = new ArrayList<>();
584 List<String> derivedFromResources = nodeType.getDerivedFrom();
585 if (derivedFromResources != null && !derivedFromResources.isEmpty()) {
587 for (String parentResource : derivedFromResources) {
588 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = derivedResourceResolver.findDerivedResources(parentResource);
589 List<GraphVertex> resources = null;
590 if (getParentResources.isRight()) {
591 log.error("Cannot find parent resource by tosca resource name {} in the graph.", parentResource);
592 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
595 resources = getParentResources.left().value();
596 if (resources == null || resources.size() == 0) {
597 log.error("Cannot find parent resource by tosca name {} in the graph. resources size is empty", parentResource);
598 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
600 if (resources.size() > 1) {
601 return handleMultipleParent(parentResource, derivedResources, resources);
603 GraphVertex parentResourceData = resources.get(0);
604 derivedResources.add(parentResourceData);
612 return Either.left(derivedResources);
615 Either<List<GraphVertex>, StorageOperationStatus> handleMultipleParent(String parentResource, List<GraphVertex> derivedResource, List<GraphVertex> fetchedDerivedResources) {
617 Either<List<GraphVertex>, StorageOperationStatus> result = Either.left(derivedResource);
619 fetchedDerivedResources.sort((d1, d2) -> {
620 return new Double(Double.parseDouble((String) d1.getMetadataProperty(GraphPropertyEnum.VERSION))).compareTo(Double.parseDouble((String) d2.getMetadataProperty(GraphPropertyEnum.VERSION)));
623 int actualHighestIndex = fetchedDerivedResources.size() - 1;
624 derivedResource.add(fetchedDerivedResources.get(actualHighestIndex));
625 fetchedDerivedResources.remove(actualHighestIndex);
627 StorageOperationStatus status = fixMultipleParent(fetchedDerivedResources);
628 if (status != StorageOperationStatus.OK) {
629 result = Either.right(status);
631 } catch (Exception e) {
632 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during handle multiple parent {}. Exception is {}", parentResource, e.getMessage());
633 result = Either.right(StorageOperationStatus.GENERAL_ERROR);
638 private StorageOperationStatus fixMultipleParent(List<GraphVertex> fetchedDerivedResources) {
639 StorageOperationStatus result = StorageOperationStatus.OK;
640 for (GraphVertex fetchedDerivedResource : fetchedDerivedResources) {
641 fetchedDerivedResource.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
642 Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(fetchedDerivedResource);
643 if (updateVertexRes.isRight()) {
644 TitanOperationStatus titatStatus = updateVertexRes.right().value();
645 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version of node type {} to false. Status is {}", fetchedDerivedResource.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME), titatStatus);
646 result = DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus);
653 private GraphVertex fillMetadata(GraphVertex nodeTypeVertex, NodeType nodeType) {
654 nodeTypeVertex.setLabel(VertexTypeEnum.NODE_TYPE);
656 fillCommonMetadata(nodeTypeVertex, nodeType);
658 return nodeTypeVertex;
662 public Either<ToscaElement, StorageOperationStatus> deleteToscaElement(GraphVertex toscaElementVertex) {
663 Either<ToscaElement, StorageOperationStatus> nodeType = getToscaElement(toscaElementVertex, new ComponentParametersView());
664 if (nodeType.isRight()) {
665 log.debug("Failed to fetch tosca element {} error {}", toscaElementVertex.getUniqueId(), nodeType.right().value());
668 TitanOperationStatus status = disassociateAndDeleteCommonElements(toscaElementVertex);
669 if (status != TitanOperationStatus.OK) {
670 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
672 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES);
673 if (status != TitanOperationStatus.OK) {
674 log.debug("Failed to disassociate capabilties for {} error {}", toscaElementVertex.getUniqueId(), status);
675 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
677 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
678 if (status != TitanOperationStatus.OK) {
679 log.debug("Failed to disassociate capabilties properties for {} error {}", toscaElementVertex.getUniqueId(), status);
680 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
682 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.REQUIREMENTS);
683 if (status != TitanOperationStatus.OK) {
684 log.debug("Failed to disassociate requirements for {} error {}", toscaElementVertex.getUniqueId(), status);
685 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
687 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ATTRIBUTES);
688 if (status != TitanOperationStatus.OK) {
689 log.debug("Failed to disassociate attributes for {} error {}", toscaElementVertex.getUniqueId(), status);
690 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
692 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.INTERFACE_ARTIFACTS);
693 if (status != TitanOperationStatus.OK) {
694 log.debug("Failed to disassociate interface artifacts for {} error {}", toscaElementVertex.getUniqueId(), status);
695 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
697 toscaElementVertex.getVertex().remove();
698 log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
703 @SuppressWarnings("unchecked")
705 public Either<NodeType, StorageOperationStatus> createToscaElement(ToscaElement toscaElement) {
706 return createNodeType((NodeType) toscaElement);
710 protected <T extends ToscaElement> TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement) {
711 return setResourceCategoryFromGraph(vertexComponent, toscaElement);
715 protected <T extends ToscaElement> StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV) {
716 return validateResourceCategory(toscaElementToUpdate, elementV);
720 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) {
722 NodeType nodeType = (NodeType) toscaElementToUpdate;
724 List<String> derivedFromResources = nodeType.getDerivedFrom();
726 // now supported only single derived from
727 if (derivedFromResources != null && !derivedFromResources.isEmpty() && derivedFromResources.get(0) != null) {
728 String firstDerived = derivedFromResources.get(0);
729 boolean derivedFromGenericType = null != nodeType.getDerivedFromGenericType();
730 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
731 if (childVertex.isRight()) {
732 TitanOperationStatus getchieldError = childVertex.right().value();
733 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchieldError);
734 return DaoStatusConverter.convertTitanStatusToStorageStatus(getchieldError);
736 GraphVertex firstDerivedInChain = childVertex.left().value();
738 String firstCurrentDerived = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME);
739 if (!firstDerived.equals(firstCurrentDerived) || derivedFromGenericType) {
741 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<>();
742 propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
744 propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, firstDerived);
745 propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
747 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, JsonParseFlagEnum.NoParse);
749 if (getParentResources.isRight()) {
750 TitanOperationStatus error = getParentResources.right().value();
751 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch derived by criteria {}. error {} ", propertiesToMatch, error);
752 return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
755 GraphVertex newDerivedV = getParentResources.left().value().get(0);
756 return updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, newDerivedV, false);
759 return StorageOperationStatus.OK;
764 * @param toscaElementToUpdate
771 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) {
772 Set<String> preDerivedChainIdList = new HashSet();
773 preDerivedChainIdList.add(preDerivedV.getUniqueId());
774 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(preDerivedV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
775 while (childVertex.isLeft()) {
776 GraphVertex currentChield = childVertex.left().value();
777 preDerivedChainIdList.add(currentChield.getUniqueId());
778 childVertex = titanDao.getChildVertex(currentChield, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
781 List<GraphVertex> derivedResources = new ArrayList<>();
782 derivedResources.add(newDerivedV);
783 StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType) toscaElementToUpdate, mergeValues, preDerivedChainIdList);
784 if (updateStatus != StorageOperationStatus.OK) {
785 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerivedV.getUniqueId(), updateStatus);
789 Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, preDerivedV, EdgeLabelEnum.DERIVED_FROM);
790 if (deleteEdge.isRight()) {
791 TitanOperationStatus deleteError = deleteEdge.right().value();
792 log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), preDerivedV.getUniqueId(), deleteError);
793 return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
796 titanDao.createEdge(nodeTypeV, newDerivedV, EdgeLabelEnum.DERIVED_FROM, new HashMap<>());
798 return StorageOperationStatus.OK;
801 private StorageOperationStatus associateDerivedDataByType(EdgeLabelEnum edgeLabel, GraphVertex nodeTypeV, NodeType nodeToUpdate, List<GraphVertex> newDerived) {
805 return associateCapabilitiesToResource(nodeTypeV, nodeToUpdate, newDerived);
807 return associateRequirementsToResource(nodeTypeV, nodeToUpdate, newDerived);
809 return associatePropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
811 return associateAttributesToResource(nodeTypeV, nodeToUpdate, newDerived);
812 case ADDITIONAL_INFORMATION:
813 return addAdditionalInformationToResource(nodeTypeV, nodeToUpdate, newDerived);
814 case CAPABILITIES_PROPERTIES:
815 return associateCapabilitiesPropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
817 return StorageOperationStatus.OK;
822 private StorageOperationStatus updateDataFromNewDerived(List<GraphVertex> newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set<String> preDerivedChainIdList) {
823 EnumSet<EdgeLabelEnum> edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION);
824 StorageOperationStatus status = null;
825 for (EdgeLabelEnum edge : edgeLabels) {
826 status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate, mergeValues, preDerivedChainIdList);
827 if (status != StorageOperationStatus.OK) {
835 private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(List<GraphVertex> newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set<String> preDerivedChainIdList) {
836 log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label);
837 Either<GraphVertex, TitanOperationStatus> dataFromGraph = getDataVertex(nodeTypeV, label);
838 if (dataFromGraph.isRight()) {
839 if (TitanOperationStatus.NOT_FOUND == dataFromGraph.right().value())
840 return associateDerivedDataByType(label, nodeTypeV, nodeElement, newDerivedList);
841 return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
843 GraphVertex dataV = dataFromGraph.left().value();
845 Map<String, T> mapFromGraph = (Map<String, T>) dataV.getJson();
846 Map<String, T> valuesFrmPrev = null;
847 if (isSimpleHierarchy(label)) {
849 valuesFrmPrev = mapFromGraph.entrySet().stream().filter(e -> e.getValue().getOwnerId() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
851 mapFromGraph.entrySet().removeIf(e -> preDerivedChainIdList.contains(e.getValue().getOwnerId()));
853 final Map<String, T> valuesFrmPrevFinal = new HashMap<>();
854 mapFromGraph.entrySet().stream().forEach(e -> {
855 T value = e.getValue();
856 value = ToscaDataDefinition.removeAndCollectByOwnerId(value, preDerivedChainIdList);
857 valuesFrmPrevFinal.put(e.getKey(), value);
859 valuesFrmPrev = valuesFrmPrevFinal;
860 mapFromGraph.entrySet().removeIf(e->e.getValue().isEmpty());
863 Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label);
864 if (dataFromDerived.isRight()) {
865 return dataFromDerived.right().value();
867 Map<String, T> dataFromDerivedAll = dataFromDerived.left().value();
869 Either<Map<String, T>, String> merged = ToscaDataDefinition.mergeDataMaps(dataFromDerivedAll, mapFromGraph);
870 if (merged.isRight()) {
871 log.debug("property {} cannot be overriden", merged.right().value());
872 return StorageOperationStatus.INVALID_PROPERTY;
874 if (mergeValues && valuesFrmPrev != null) {
875 valuesFrmPrev.entrySet().forEach(e -> {
876 T newData = merged.left().value().get(e.getKey());
877 if (newData != null) {
878 if (isSimpleHierarchy(label)) {
879 e.getValue().mergeFunction(newData, true);
881 e.getValue().updateIfExist(newData, true);
886 dataV.setJson(dataFromDerivedAll);
887 Either<GraphVertex, TitanOperationStatus> updateDataV = updateOrCopyOnUpdate(dataV, nodeTypeV, label);
888 if (updateDataV.isRight()) {
889 return DaoStatusConverter.convertTitanStatusToStorageStatus(updateDataV.right().value());
891 return StorageOperationStatus.OK;
894 private boolean isSimpleHierarchy(EdgeLabelEnum label) {
898 case ADDITIONAL_INFORMATION:
909 public <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) {
910 fillMetadata(elementV, (NodeType) toscaElementToUpdate);
913 public Either<ToscaElement, StorageOperationStatus> shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) {
914 NodeType nodeType = (NodeType) toscaElementToUpdate;
916 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
917 if (childVertex.isRight()) {
918 TitanOperationStatus getchildError = childVertex.right().value();
919 if (getchildError == TitanOperationStatus.NOT_FOUND) {
920 log.debug("derived resource for element {} not found", nodeTypeV.getUniqueId());
921 return Either.right(StorageOperationStatus.OK);
924 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchildError);
925 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getchildError));
927 GraphVertex firstDerivedInChain = childVertex.left().value();
929 String currentVersion = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.VERSION);
931 Map<GraphPropertyEnum, Object> props = new HashMap<>();
932 props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeType.getDerivedFrom().get(0));
933 props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
934 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
936 Map<GraphPropertyEnum, Object> propsHasNot = new HashMap<>();
937 propsHasNot.put(GraphPropertyEnum.IS_DELETED, true);
938 Either<List<GraphVertex>, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, props, propsHasNot, JsonParseFlagEnum.NoParse);
939 if (byCriteria.isRight()) {
940 log.debug("Failed to fetch derived by props {} error {}", props, byCriteria.right().value());
941 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
943 List<GraphVertex> lastDerived = byCriteria.left().value();
944 // now supported only one derived!!! Change in future!(Evg)
945 GraphVertex derivedFromHighest = lastDerived.get(0);
946 String highestVersion = (String) derivedFromHighest.getMetadataProperty(GraphPropertyEnum.VERSION);
947 if (!highestVersion.equals(currentVersion)) {
949 // need to update to latest version of derived from
950 StorageOperationStatus updateDerived = updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, derivedFromHighest, true);
952 if (updateDerived != StorageOperationStatus.OK) {
953 log.debug("Failed to update {} to highest derived {} from error {}", nodeTypeV.getUniqueId(), derivedFromHighest.getUniqueId(), updateDerived);
954 return Either.right(updateDerived);
956 return getToscaElement(nodeTypeV.getUniqueId(), new ComponentParametersView());
958 // no version changes
959 return Either.right(StorageOperationStatus.OK);