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 java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.EnumSet;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
31 import java.util.regex.Pattern;
32 import java.util.stream.Collectors;
34 import org.apache.tinkerpop.gremlin.structure.Direction;
35 import org.apache.tinkerpop.gremlin.structure.Edge;
36 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
37 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
38 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
39 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
40 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
41 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
42 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
48 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
49 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
50 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
51 import org.openecomp.sdc.be.model.ComponentParametersView;
52 import org.openecomp.sdc.be.model.DerivedNodeTypeResolver;
53 import org.openecomp.sdc.be.model.LifecycleStateEnum;
54 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
55 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
56 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
57 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
58 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
59 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
60 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
61 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64 import org.springframework.beans.factory.annotation.Qualifier;
66 import fj.data.Either;
68 @org.springframework.stereotype.Component("node-type-operation")
69 public class NodeTypeOperation extends ToscaElementOperation {
70 public static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
71 public static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
73 private static Logger log = LoggerFactory.getLogger(NodeTypeOperation.class.getName());
75 private DerivedNodeTypeResolver derivedResourceResolver;
77 public NodeTypeOperation(@Qualifier("derived-resource-resolver") DerivedNodeTypeResolver derivedNodeTypeResolver) {
78 this.derivedResourceResolver = derivedNodeTypeResolver;
81 public Either<NodeType, StorageOperationStatus> createNodeType(NodeType nodeType) {
83 Either<NodeType, StorageOperationStatus> result = null;
85 nodeType.generateUUID();
87 nodeType = getResourceMetaDataFromResource(nodeType);
88 String resourceUniqueId = nodeType.getUniqueId();
89 if (resourceUniqueId == null) {
90 resourceUniqueId = UniqueIdBuilder.buildResourceUniqueId();
91 nodeType.setUniqueId(resourceUniqueId);
94 // get derived from resources
95 List<GraphVertex> derivedResources = null;
96 Either<List<GraphVertex>, StorageOperationStatus> derivedResourcesResult = findDerivedResources(nodeType);
97 if (derivedResourcesResult.isRight()) {
98 result = Either.right(derivedResourcesResult.right().value());
101 derivedResources = derivedResourcesResult.left().value();
104 GraphVertex nodeTypeVertex = new GraphVertex(VertexTypeEnum.NODE_TYPE);
105 fillToscaElementVertexData(nodeTypeVertex, nodeType, JsonParseFlagEnum.ParseAll);
107 Either<GraphVertex, TitanOperationStatus> createdVertex = titanDao.createVertex(nodeTypeVertex);
108 if (createdVertex.isRight()) {
109 TitanOperationStatus status = createdVertex.right().value();
110 log.error("Error returned after creating resource data node {}. status returned is ", nodeTypeVertex, status);
111 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
114 nodeTypeVertex = createdVertex.left().value();
116 StorageOperationStatus assosiateCommon = assosiateCommonForToscaElement(nodeTypeVertex, nodeType, derivedResources);
117 if (assosiateCommon != StorageOperationStatus.OK) {
118 result = Either.right(assosiateCommon);
122 StorageOperationStatus associateDerived = assosiateToDerived(nodeTypeVertex, derivedResources);
123 if (associateDerived != StorageOperationStatus.OK) {
124 result = Either.right(associateDerived);
127 StorageOperationStatus associateCategory = assosiateResourceMetadataToCategory(nodeTypeVertex, nodeType);
128 if (associateCategory != StorageOperationStatus.OK) {
129 result = Either.right(associateCategory);
133 StorageOperationStatus associateAttributes = associateAttributesToResource(nodeTypeVertex, nodeType, derivedResources);
134 if (associateAttributes != StorageOperationStatus.OK) {
135 result = Either.right(associateAttributes);
139 StorageOperationStatus associateRequirements = associateRequirementsToResource(nodeTypeVertex, nodeType, derivedResources);
140 if (associateRequirements != StorageOperationStatus.OK) {
141 result = Either.right(associateRequirements);
145 StorageOperationStatus associateCapabilities = associateCapabilitiesToResource(nodeTypeVertex, nodeType, derivedResources);
146 if (associateCapabilities != StorageOperationStatus.OK) {
147 result = Either.right(associateCapabilities);
150 StorageOperationStatus associateCapabilitiesProps = associateCapabilitiesPropertiesToResource(nodeTypeVertex, nodeType, derivedResources);
151 if (associateCapabilitiesProps != StorageOperationStatus.OK) {
152 result = Either.right(associateCapabilitiesProps);
156 StorageOperationStatus associateInterfaces = associateInterfacesToResource(nodeTypeVertex, nodeType, derivedResources);
157 if (associateInterfaces != StorageOperationStatus.OK) {
158 result = Either.right(associateInterfaces);
162 StorageOperationStatus addAdditionalInformation = addAdditionalInformationToResource(nodeTypeVertex, nodeType, derivedResources);
163 if (addAdditionalInformation != StorageOperationStatus.OK) {
164 result = Either.right(addAdditionalInformation);
167 result = Either.left(nodeType);
172 private StorageOperationStatus associateInterfacesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
173 // Note : currently only one derived supported!!!!
174 Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.INTERFACE_ARTIFACTS);
175 if (dataFromDerived.isRight()) {
176 return dataFromDerived.right().value();
178 Map<String, InterfaceDataDefinition> interfacArtsAll = dataFromDerived.left().value();
180 Map<String, InterfaceDataDefinition> interfacArts = nodeType.getInterfaceArtifacts();
181 if (interfacArts != null) {
182 interfacArtsAll.putAll(interfacArts);
184 if (!interfacArtsAll.isEmpty()) {
185 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.INTERFACE_ARTIFACTS, EdgeLabelEnum.INTERFACE_ARTIFACTS, interfacArtsAll);
186 if (assosiateElementToData.isRight()) {
187 return assosiateElementToData.right().value();
190 return StorageOperationStatus.OK;
194 public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId, ComponentParametersView componentParametersView) {
196 Either<GraphVertex, StorageOperationStatus> componentByLabelAndId = getComponentByLabelAndId(uniqueId, ToscaElementTypeEnum.NodeType, JsonParseFlagEnum.ParseMetadata);
197 if (componentByLabelAndId.isRight()) {
198 return Either.right(componentByLabelAndId.right().value());
200 GraphVertex componentV = componentByLabelAndId.left().value();
202 return getToscaElement(componentV, componentParametersView);
206 // -------------------------------------------------------------
208 public Either<ToscaElement, StorageOperationStatus> getToscaElement(GraphVertex componentV, ComponentParametersView componentParametersView) {
209 NodeType toscaElement;
210 toscaElement = convertToComponent(componentV);
211 TitanOperationStatus status = null;
212 if (false == componentParametersView.isIgnoreUsers()) {
213 status = setCreatorFromGraph(componentV, toscaElement);
214 if (status != TitanOperationStatus.OK) {
215 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
218 status = setLastModifierFromGraph(componentV, toscaElement);
219 if (status != TitanOperationStatus.OK) {
220 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
224 if (false == componentParametersView.isIgnoreProperties()) {
225 status = setResourcePropertiesFromGraph(componentV, toscaElement);
226 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
227 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
231 if (false == componentParametersView.isIgnoreAttributesFrom()) {
232 status = setResourceAttributesFromGraph(componentV, toscaElement);
233 if (status != TitanOperationStatus.OK) {
234 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
238 if (false == componentParametersView.isIgnoreDerivedFrom()) {
239 status = setResourceDerivedFromGraph(componentV, toscaElement);
240 if (status != TitanOperationStatus.OK) {
241 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
245 if (false == componentParametersView.isIgnoreCategories()) {
246 status = setResourceCategoryFromGraph(componentV, toscaElement);
247 if (status != TitanOperationStatus.OK) {
248 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
251 if (false == componentParametersView.isIgnoreRequirements()) {
252 status = setResourceRequirementsFromGraph(componentV, toscaElement);
253 if (status != TitanOperationStatus.OK) {
254 log.error("Failed to set requirement of resource {}. status is {}", componentV.getUniqueId(), status);
255 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
258 if (false == componentParametersView.isIgnoreCapabilities()) {
259 status = setResourceCapabilitiesFromGraph(componentV, toscaElement);
260 if (status != TitanOperationStatus.OK) {
261 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
265 if (false == componentParametersView.isIgnoreArtifacts()) {
266 status = setArtifactsFromGraph(componentV, toscaElement);
267 if (status != TitanOperationStatus.OK) {
268 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
271 if (false == componentParametersView.isIgnoreAdditionalInformation()) {
272 status = setAdditionalInformationFromGraph(componentV, toscaElement);
273 if (status != TitanOperationStatus.OK) {
274 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
277 if (false == componentParametersView.isIgnoreInterfaces()) {
278 status = setInterfacesFromGraph(componentV, toscaElement);
279 if (status != TitanOperationStatus.OK) {
280 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
283 if (false == componentParametersView.isIgnoreAllVersions()) {
284 status = setAllVersions(componentV, toscaElement);
285 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
286 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
290 if (false == componentParametersView.isIgnoreCapabiltyProperties()) {
291 status = setComponentCapPropertiesFromGraph(componentV, toscaElement);
292 if (status != TitanOperationStatus.OK) {
293 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
297 return Either.left(toscaElement);
300 private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
301 Either<Map<String, MapPropertiesDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
302 if (result.isLeft()) {
303 toscaElement.setCapabiltiesProperties(result.left().value());
305 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
306 return result.right().value();
309 return TitanOperationStatus.OK;
312 private TitanOperationStatus setInterfacesFromGraph(GraphVertex componentV, NodeType toscaElement) {
313 Either<Map<String, InterfaceDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.INTERFACE_ARTIFACTS);
314 if (result.isLeft()) {
315 toscaElement.setInterfaceArtifacts(result.left().value());
317 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
318 return result.right().value();
321 return TitanOperationStatus.OK;
324 protected <T extends ToscaElement> TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement) {
325 return setResourceCapabilitiesFromGraph(componentV, (NodeType) toscaElement);
328 private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
329 Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
330 if (result.isLeft()) {
331 toscaElement.setCapabilties(result.left().value());
333 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
334 return result.right().value();
337 return TitanOperationStatus.OK;
340 private TitanOperationStatus setResourceDerivedFromGraph(GraphVertex componentV, NodeType toscaElement) {
341 List<String> derivedFromList = new ArrayList<String>();
343 TitanOperationStatus listFromGraphStatus = findResourcesPathRecursively(componentV, derivedFromList);
344 if (TitanOperationStatus.OK != listFromGraphStatus) {
345 return listFromGraphStatus;
348 if (false == derivedFromList.isEmpty()) {
349 if (derivedFromList.size() > 1) {
350 List<String> lastDerivedFrom = new ArrayList<String>();
351 lastDerivedFrom.add(derivedFromList.get(1));
352 toscaElement.setDerivedFrom(lastDerivedFrom);
353 toscaElement.setDerivedList(derivedFromList);
355 toscaElement.setDerivedFrom(null);
356 toscaElement.setDerivedList(derivedFromList);
360 return TitanOperationStatus.OK;
363 protected TitanOperationStatus findResourcesPathRecursively(GraphVertex nodeTypeV, List<String> resourcesPathList) {
364 Either<GraphVertex, TitanOperationStatus> parentResourceRes = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
365 resourcesPathList.add((String) nodeTypeV.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
366 while (parentResourceRes.isLeft()) {
368 GraphVertex parent = parentResourceRes.left().value();
369 resourcesPathList.add((String) parent.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
370 parentResourceRes = titanDao.getChildVertex(parent, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
372 TitanOperationStatus operationStatus = parentResourceRes.right().value();
374 if (operationStatus != TitanOperationStatus.NOT_FOUND) {
375 return operationStatus;
377 return TitanOperationStatus.OK;
382 protected <T extends ToscaElement> TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) {
383 return setResourceRequirementsFromGraph(componentV, (NodeType) toscaElement);
386 private TitanOperationStatus setResourceRequirementsFromGraph(GraphVertex componentV, NodeType toscaElement) {
387 Either<Map<String, ListRequirementDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS);
388 if (result.isLeft()) {
389 toscaElement.setRequirements(result.left().value());
391 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
392 return result.right().value();
395 return TitanOperationStatus.OK;
398 private TitanOperationStatus setResourceAttributesFromGraph(GraphVertex componentV, NodeType toscaElement) {
399 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
400 if (result.isLeft()) {
401 toscaElement.setAttributes(result.left().value());
403 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
404 return result.right().value();
407 return TitanOperationStatus.OK;
410 private TitanOperationStatus setResourcePropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
411 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.PROPERTIES);
412 if (result.isLeft()) {
413 toscaElement.setProperties(result.left().value());
415 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
416 return result.right().value();
419 return TitanOperationStatus.OK;
422 private StorageOperationStatus assosiateToDerived(GraphVertex nodeTypeVertex, List<GraphVertex> derivedResources) {
423 for (GraphVertex derivedV : derivedResources) {
424 TitanOperationStatus createEdge = titanDao.createEdge(nodeTypeVertex, derivedV, EdgeLabelEnum.DERIVED_FROM, null);
425 if (createEdge != TitanOperationStatus.OK) {
426 log.trace("Failed to associate resource {} to derived with id {}", nodeTypeVertex.getUniqueId(), derivedV.getUniqueId());
427 return DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge);
430 return StorageOperationStatus.OK;
433 private StorageOperationStatus addAdditionalInformationToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
434 // Note : currently only one derived supported!!!!
435 Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION);
436 if (dataFromDerived.isRight()) {
437 return dataFromDerived.right().value();
439 Map<String, AdditionalInfoParameterDataDefinition> addInformationAll = dataFromDerived.left().value();
441 Map<String, AdditionalInfoParameterDataDefinition> addInformation = nodeType.getAdditionalInformation();
442 if (addInformation != null) {
443 ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation);
445 if (!addInformationAll.isEmpty()) {
446 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, addInformationAll);
447 if (assosiateElementToData.isRight()) {
448 return assosiateElementToData.right().value();
451 return StorageOperationStatus.OK;
454 private StorageOperationStatus associateCapabilitiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
455 // Note : currently only one derived supported!!!!
456 Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES);
457 if (dataFromDerived.isRight()) {
458 return dataFromDerived.right().value();
460 Map<String, ListCapabilityDataDefinition> capabiltiesAll = dataFromDerived.left().value();
462 Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilties();
463 if (capabilties != null) {
464 if (capabiltiesAll == null) {
465 capabiltiesAll = new HashMap<>();
467 capabilties.values().forEach(l -> {
468 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
469 String uid = UniqueIdBuilder.buildCapabilityUid(nodeTypeVertex.getUniqueId(), p.getName());
474 ToscaDataDefinition.mergeDataMaps(capabiltiesAll, capabilties);
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);
486 capabiltiesAll.values().forEach(l -> {
487 l.getListToscaDataDefinition().forEach(c -> {
488 List<String> capabilitySources = c.getCapabilitySources();
489 if (capabilitySources == null) {
490 capabilitySources = new ArrayList<>();
492 capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
493 c.setCapabilitySources(capabilitySources);
496 if (!capabiltiesAll.isEmpty()) {
497 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
498 if (assosiateElementToData.isRight()) {
499 return assosiateElementToData.right().value();
502 return StorageOperationStatus.OK;
505 private StorageOperationStatus associateRequirementsToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
506 // Note : currently only one derived supported!!!!
507 Either<Map<String, ListRequirementDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.REQUIREMENTS);
508 if (dataFromDerived.isRight()) {
509 return dataFromDerived.right().value();
511 Map<String, ListRequirementDataDefinition> requirementsAll = dataFromDerived.left().value();
513 Map<String, ListRequirementDataDefinition> requirements = nodeType.getRequirements();
514 if (requirements != null) {
515 if (requirementsAll == null) {
516 requirementsAll = new HashMap<>();
518 requirements.values().forEach(l -> {
519 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
520 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
525 ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements);
528 if (!requirementsAll.isEmpty()) {
529 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, EdgeLabelEnum.REQUIREMENTS, requirementsAll);
530 if (assosiateElementToData.isRight()) {
531 return assosiateElementToData.right().value();
534 return StorageOperationStatus.OK;
537 private StorageOperationStatus associateAttributesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
538 // Note : currently only one derived supported!!!!
539 Either<Map<String, PropertyDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ATTRIBUTES);
540 if (dataFromDerived.isRight()) {
541 return dataFromDerived.right().value();
543 Map<String, PropertyDataDefinition> attributesAll = dataFromDerived.left().value();
545 Map<String, PropertyDataDefinition> attributes = nodeType.getAttributes();
546 if (attributes != null) {
547 attributes.values().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
548 String uid = UniqueIdBuilder.buildAttributeUid(nodeTypeVertex.getUniqueId(), p.getName());
551 ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
553 if (!attributesAll.isEmpty()) {
554 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
555 if (assosiateElementToData.isRight()) {
556 return assosiateElementToData.right().value();
559 return StorageOperationStatus.OK;
562 // TODO get from derived
563 private StorageOperationStatus associateCapabilitiesPropertiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
564 // // Note : currently only one derived supported!!!!
565 Either<Map<String, MapPropertiesDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
566 if (dataFromDerived.isRight()) {
567 return dataFromDerived.right().value();
569 Map<String, MapPropertiesDataDefinition> propertiesAll = dataFromDerived.left().value();
570 Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabiltiesProperties();
571 if (capabiltiesProps != null) {
572 capabiltiesProps.values().forEach(l -> {
573 if (l.getMapToscaDataDefinition() != null && l.getMapToscaDataDefinition().values() != null) {
574 Collection<PropertyDataDefinition> mapToscaDataDefinition = l.getMapToscaDataDefinition().values();
575 mapToscaDataDefinition.stream().filter(p -> p != null && p.getUniqueId() == null).forEach(p -> {
576 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
581 ToscaDataDefinition.mergeDataMaps(propertiesAll, capabiltiesProps);
583 if (!propertiesAll.isEmpty()) {
584 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, propertiesAll);
585 if (assosiateElementToData.isRight()) {
586 return assosiateElementToData.right().value();
589 return StorageOperationStatus.OK;
592 public Either<List<GraphVertex>, StorageOperationStatus> findDerivedResources(NodeType nodeType) {
594 List<GraphVertex> derivedResources = new ArrayList<GraphVertex>();
595 List<String> derivedFromResources = nodeType.getDerivedFrom();
596 if (derivedFromResources != null && false == derivedFromResources.isEmpty()) {
598 for (String parentResource : derivedFromResources) {
599 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = derivedResourceResolver.findDerivedResources(parentResource);
600 List<GraphVertex> resources = null;
601 if (getParentResources.isRight()) {
602 log.error("Cannot find parent resource by tosca resource name {} in the graph.", parentResource);
603 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
606 resources = getParentResources.left().value();
607 if (resources == null || resources.size() == 0) {
608 log.error("Cannot find parent resource by tosca name {} in the graph. resources size is empty", parentResource);
609 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
611 if (resources.size() > 1) {
612 return handleMultipleParent(parentResource, derivedResources, resources);
614 GraphVertex parentResourceData = resources.get(0);
615 derivedResources.add(parentResourceData);
623 return Either.left(derivedResources);
626 Either<List<GraphVertex>, StorageOperationStatus> handleMultipleParent(String parentResource, List<GraphVertex> derivedResource, List<GraphVertex> fetchedDerivedResources) {
628 Either<List<GraphVertex>, StorageOperationStatus> result = Either.left(derivedResource);
630 fetchedDerivedResources.sort((d1, d2) -> {
631 return new Double(Double.parseDouble((String) d1.getMetadataProperty(GraphPropertyEnum.VERSION))).compareTo(Double.parseDouble((String) d2.getMetadataProperty(GraphPropertyEnum.VERSION)));
634 int actualHighestIndex = fetchedDerivedResources.size() - 1;
635 derivedResource.add(fetchedDerivedResources.get(actualHighestIndex));
636 fetchedDerivedResources.remove(actualHighestIndex);
638 StorageOperationStatus status = fixMultipleParent(fetchedDerivedResources);
639 if (status != StorageOperationStatus.OK) {
640 result = Either.right(status);
642 } catch (Exception e) {
643 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during handle multiple parent {}. Exception is {}", parentResource, e.getMessage());
644 result = Either.right(StorageOperationStatus.GENERAL_ERROR);
649 private StorageOperationStatus fixMultipleParent(List<GraphVertex> fetchedDerivedResources) {
650 StorageOperationStatus result = StorageOperationStatus.OK;
651 for (GraphVertex fetchedDerivedResource : fetchedDerivedResources) {
652 fetchedDerivedResource.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
653 Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(fetchedDerivedResource);
654 if (updateVertexRes.isRight()) {
655 TitanOperationStatus titatStatus = updateVertexRes.right().value();
656 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version of node type {} to false. Status is {}", fetchedDerivedResource.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME), titatStatus);
657 result = DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus);
664 private GraphVertex fillMetadata(GraphVertex nodeTypeVertex, NodeType nodeType) {
665 nodeTypeVertex.setLabel(VertexTypeEnum.NODE_TYPE);
667 fillCommonMetadata(nodeTypeVertex, nodeType);
669 return nodeTypeVertex;
673 public Either<ToscaElement, StorageOperationStatus> deleteToscaElement(GraphVertex toscaElementVertex) {
674 Either<ToscaElement, StorageOperationStatus> nodeType = getToscaElement(toscaElementVertex, new ComponentParametersView());
675 if (nodeType.isRight()) {
676 log.debug("Failed to fetch tosca element {} error {}", toscaElementVertex.getUniqueId(), nodeType.right().value());
679 TitanOperationStatus status = disassociateAndDeleteCommonElements(toscaElementVertex);
680 if (status != TitanOperationStatus.OK) {
681 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
683 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES);
684 if (status != TitanOperationStatus.OK) {
685 log.debug("Failed to disassociate capabilties for {} error {}", toscaElementVertex.getUniqueId(), status);
686 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
688 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
689 if (status != TitanOperationStatus.OK) {
690 log.debug("Failed to disassociate capabilties properties for {} error {}", toscaElementVertex.getUniqueId(), status);
691 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
693 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.REQUIREMENTS);
694 if (status != TitanOperationStatus.OK) {
695 log.debug("Failed to disassociate requirements for {} error {}", toscaElementVertex.getUniqueId(), status);
696 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
698 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ATTRIBUTES);
699 if (status != TitanOperationStatus.OK) {
700 log.debug("Failed to disassociate attributes for {} error {}", toscaElementVertex.getUniqueId(), status);
701 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
703 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.INTERFACE_ARTIFACTS);
704 if (status != TitanOperationStatus.OK) {
705 log.debug("Failed to disassociate interface artifacts for {} error {}", toscaElementVertex.getUniqueId(), status);
706 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
708 toscaElementVertex.getVertex().remove();
709 log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
714 @SuppressWarnings("unchecked")
716 public Either<NodeType, StorageOperationStatus> createToscaElement(ToscaElement toscaElement) {
717 return createNodeType((NodeType) toscaElement);
721 protected <T extends ToscaElement> TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement) {
722 return setResourceCategoryFromGraph(vertexComponent, toscaElement);
726 protected <T extends ToscaElement> StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV) {
727 return validateResourceCategory(toscaElementToUpdate, elementV);
731 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) {
733 NodeType nodeType = (NodeType) toscaElementToUpdate;
734 List<GraphVertex> derivedResources = new ArrayList<>();
736 List<String> derivedFromResources = nodeType.getDerivedFrom();
738 // now supported only single derived from
739 if (derivedFromResources != null && !derivedFromResources.isEmpty() && derivedFromResources.get(0) != null) {
740 String firstDerived = derivedFromResources.get(0);
741 boolean derivedFromGenericType = null != nodeType.getDerivedFromGenericType();
742 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
743 if (childVertex.isRight()) {
744 TitanOperationStatus getchieldError = childVertex.right().value();
745 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchieldError);
746 return DaoStatusConverter.convertTitanStatusToStorageStatus(getchieldError);
748 GraphVertex firstDerivedInChain = childVertex.left().value();
750 String firstCurrentDerived = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME);
751 if (!firstDerived.equals(firstCurrentDerived) || derivedFromGenericType) {
753 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<GraphPropertyEnum, Object>();
754 propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
756 propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, firstDerived);
757 propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
759 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, JsonParseFlagEnum.NoParse);
761 if (getParentResources.isRight()) {
762 TitanOperationStatus error = getParentResources.right().value();
763 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch derived by criteria {}. error {} ", propertiesToMatch, error);
764 return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
767 GraphVertex newDerivedV = getParentResources.left().value().get(0);
768 return updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, newDerivedV, false);
771 return StorageOperationStatus.OK;
776 * @param toscaElementToUpdate
783 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) {
784 Set<String> preDerivedChainIdList = new HashSet();
785 preDerivedChainIdList.add(preDerivedV.getUniqueId());
786 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(preDerivedV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
787 while (childVertex.isLeft()) {
788 GraphVertex currentChield = childVertex.left().value();
789 preDerivedChainIdList.add(currentChield.getUniqueId());
790 childVertex = titanDao.getChildVertex(currentChield, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
793 List<GraphVertex> derivedResources = new ArrayList<>();
794 derivedResources.add(newDerivedV);
795 StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType) toscaElementToUpdate, mergeValues, preDerivedChainIdList);
796 if (updateStatus != StorageOperationStatus.OK) {
797 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerivedV.getUniqueId(), updateStatus);
801 Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, preDerivedV, EdgeLabelEnum.DERIVED_FROM);
802 if (deleteEdge.isRight()) {
803 TitanOperationStatus deleteError = deleteEdge.right().value();
804 log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), preDerivedV.getUniqueId(), deleteError);
805 return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
808 titanDao.createEdge(nodeTypeV, newDerivedV, EdgeLabelEnum.DERIVED_FROM, new HashMap<>());
810 return StorageOperationStatus.OK;
813 private StorageOperationStatus associateDerivedDataByType(EdgeLabelEnum edgeLabel, GraphVertex nodeTypeV, NodeType nodeToUpdate, List<GraphVertex> newDerived) {
817 return associateCapabilitiesToResource(nodeTypeV, nodeToUpdate, newDerived);
819 return associateRequirementsToResource(nodeTypeV, nodeToUpdate, newDerived);
821 return associatePropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
823 return associateAttributesToResource(nodeTypeV, nodeToUpdate, newDerived);
824 case ADDITIONAL_INFORMATION:
825 return addAdditionalInformationToResource(nodeTypeV, nodeToUpdate, newDerived);
826 case CAPABILITIES_PROPERTIES:
827 return associateCapabilitiesPropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
829 return StorageOperationStatus.OK;
834 private StorageOperationStatus updateDataFromNewDerived(List<GraphVertex> newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set<String> preDerivedChainIdList) {
835 EnumSet<EdgeLabelEnum> edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION);
836 StorageOperationStatus status = null;
837 for (EdgeLabelEnum edge : edgeLabels) {
838 status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate, mergeValues, preDerivedChainIdList);
839 if (status != StorageOperationStatus.OK) {
847 private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(List<GraphVertex> newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set<String> preDerivedChainIdList) {
848 log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label);
849 Either<GraphVertex, TitanOperationStatus> dataFromGraph = getDataVertex(nodeTypeV, label);
850 if (dataFromGraph.isRight()) {
851 if (TitanOperationStatus.NOT_FOUND == dataFromGraph.right().value())
852 return associateDerivedDataByType(label, nodeTypeV, nodeElement, newDerivedList);
853 return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
855 GraphVertex dataV = dataFromGraph.left().value();
857 Map<String, T> mapFromGraph = (Map<String, T>) dataV.getJson();
858 Map<String, T> valuesFrmPrev = null;
859 if (isSimpleHierarchy(label)) {
861 valuesFrmPrev = mapFromGraph.entrySet().stream().filter(e -> e.getValue().getOwnerId() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
863 mapFromGraph.entrySet().removeIf(e -> preDerivedChainIdList.contains(e.getValue().getOwnerId()));
865 final Map<String, T> valuesFrmPrevFinal = new HashMap<>();
866 mapFromGraph.entrySet().stream().forEach(e -> {
867 T value = e.getValue();
868 value = ToscaDataDefinition.removeAndCollectByOwnerId(value, preDerivedChainIdList);
869 valuesFrmPrevFinal.put(e.getKey(), value);
871 valuesFrmPrev = valuesFrmPrevFinal;
872 mapFromGraph.entrySet().removeIf(e->e.getValue().isEmpty());
875 Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label);
876 if (dataFromDerived.isRight()) {
877 return dataFromDerived.right().value();
879 Map<String, T> dataFromDerivedAll = dataFromDerived.left().value();
881 Either<Map<String, T>, String> merged = ToscaDataDefinition.mergeDataMaps(dataFromDerivedAll, mapFromGraph);
882 if (merged.isRight()) {
883 log.debug("property {} cannot be overriden", merged.right().value());
884 return StorageOperationStatus.INVALID_PROPERTY;
886 if (mergeValues && valuesFrmPrev != null) {
887 valuesFrmPrev.entrySet().forEach(e -> {
888 T newData = merged.left().value().get(e.getKey());
889 if (newData != null) {
890 if (isSimpleHierarchy(label)) {
891 e.getValue().mergeFunction(newData, true);
893 e.getValue().updateIfExist(newData, true);
898 dataV.setJson(dataFromDerivedAll);
899 Either<GraphVertex, TitanOperationStatus> updateDataV = updateOrCopyOnUpdate(dataV, nodeTypeV, label);
900 if (updateDataV.isRight()) {
901 return DaoStatusConverter.convertTitanStatusToStorageStatus(updateDataV.right().value());
903 return StorageOperationStatus.OK;
906 private boolean isSimpleHierarchy(EdgeLabelEnum label) {
910 case ADDITIONAL_INFORMATION:
921 public <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) {
922 fillMetadata(elementV, (NodeType) toscaElementToUpdate);
925 public Either<ToscaElement, StorageOperationStatus> shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) {
926 NodeType nodeType = (NodeType) toscaElementToUpdate;
928 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
929 if (childVertex.isRight()) {
930 TitanOperationStatus getchildError = childVertex.right().value();
931 if (getchildError == TitanOperationStatus.NOT_FOUND) {
932 log.debug("derived resource for element {} not found", nodeTypeV.getUniqueId());
933 return Either.right(StorageOperationStatus.OK);
936 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchildError);
937 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getchildError));
939 GraphVertex firstDerivedInChain = childVertex.left().value();
941 String currentVersion = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.VERSION);
943 Map<GraphPropertyEnum, Object> props = new HashMap<>();
944 props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeType.getDerivedFrom().get(0));
945 props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
946 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
948 Map<GraphPropertyEnum, Object> propsHasNot = new HashMap<>();
949 propsHasNot.put(GraphPropertyEnum.IS_DELETED, true);
950 Either<List<GraphVertex>, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, props, propsHasNot, JsonParseFlagEnum.NoParse);
951 if (byCriteria.isRight()) {
952 log.debug("Failed to fetch derived by props {} error {}", props, byCriteria.right().value());
953 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
955 List<GraphVertex> lastDerived = byCriteria.left().value();
956 // now supported only one derived!!! Change in future!(Evg)
957 GraphVertex derivedFromHighest = lastDerived.get(0);
958 String highestVersion = (String) derivedFromHighest.getMetadataProperty(GraphPropertyEnum.VERSION);
959 if (!highestVersion.equals(currentVersion)) {
961 // need to update to latest version of derived from
962 StorageOperationStatus updateDerived = updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, derivedFromHighest, true);
964 if (updateDerived != StorageOperationStatus.OK) {
965 log.debug("Failed to update {} to highest derived {} from error {}", nodeTypeV.getUniqueId(), derivedFromHighest.getUniqueId(), updateDerived);
966 return Either.right(updateDerived);
968 return getToscaElement(nodeTypeV.getUniqueId(), new ComponentParametersView());
970 // no version changes
971 return Either.right(StorageOperationStatus.OK);