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.ListRequirementDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
47 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
48 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
49 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
50 import org.openecomp.sdc.be.model.ComponentParametersView;
51 import org.openecomp.sdc.be.model.DerivedNodeTypeResolver;
52 import org.openecomp.sdc.be.model.LifecycleStateEnum;
53 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
54 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
55 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
58 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
59 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
60 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63 import org.springframework.beans.factory.annotation.Qualifier;
65 import fj.data.Either;
67 @org.springframework.stereotype.Component("node-type-operation")
68 public class NodeTypeOperation extends ToscaElementOperation {
69 public final static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
70 public final static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
72 private static Logger log = LoggerFactory.getLogger(NodeTypeOperation.class.getName());
74 private DerivedNodeTypeResolver derivedResourceResolver;
76 public NodeTypeOperation(@Qualifier("derived-resource-resolver") DerivedNodeTypeResolver derivedNodeTypeResolver) {
77 this.derivedResourceResolver = derivedNodeTypeResolver;
80 public Either<NodeType, StorageOperationStatus> createNodeType(NodeType nodeType) {
82 Either<NodeType, StorageOperationStatus> result = null;
84 nodeType.generateUUID();
86 //Set missing props such as names, default lifecycle state, dates etc...
87 nodeType = getResourceMetaDataFromResource(nodeType);
90 String resourceUniqueId = nodeType.getUniqueId();
91 if (resourceUniqueId == null) {
92 resourceUniqueId = UniqueIdBuilder.buildResourceUniqueId();
93 nodeType.setUniqueId(resourceUniqueId);
96 // get derived from resources
97 List<GraphVertex> derivedResources = null;
98 Either<List<GraphVertex>, StorageOperationStatus> derivedResourcesResult = findDerivedResources(nodeType);
99 if (derivedResourcesResult.isRight()) {
100 result = Either.right(derivedResourcesResult.right().value());
103 derivedResources = derivedResourcesResult.left().value();
106 //Create Vertext Object and fill according to given NodeType
107 GraphVertex nodeTypeVertex = new GraphVertex(VertexTypeEnum.NODE_TYPE);
108 fillToscaElementVertexData(nodeTypeVertex, nodeType, JsonParseFlagEnum.ParseAll);
110 //Create Node Type in Graph
111 Either<GraphVertex, TitanOperationStatus> createdVertex = titanDao.createVertex(nodeTypeVertex);
112 if (createdVertex.isRight()) {
113 TitanOperationStatus status = createdVertex.right().value();
114 log.error("Error returned after creating resource data node {}. status returned is ", nodeTypeVertex, status);
115 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
118 nodeTypeVertex = createdVertex.left().value();
120 StorageOperationStatus assosiateCommon = assosiateCommonForToscaElement(nodeTypeVertex, nodeType, derivedResources);
121 if (assosiateCommon != StorageOperationStatus.OK) {
122 result = Either.right(assosiateCommon);
126 StorageOperationStatus associateDerived = assosiateToDerived(nodeTypeVertex, derivedResources);
127 if (associateDerived != StorageOperationStatus.OK) {
128 result = Either.right(associateDerived);
131 StorageOperationStatus associateCategory = assosiateResourceMetadataToCategory(nodeTypeVertex, nodeType);
132 if (associateCategory != StorageOperationStatus.OK) {
133 result = Either.right(associateCategory);
137 StorageOperationStatus associateAttributes = associateAttributesToResource(nodeTypeVertex, nodeType, derivedResources);
138 if (associateAttributes != StorageOperationStatus.OK) {
139 result = Either.right(associateAttributes);
143 StorageOperationStatus associateRequirements = associateRequirementsToResource(nodeTypeVertex, nodeType, derivedResources);
144 if (associateRequirements != StorageOperationStatus.OK) {
145 result = Either.right(associateRequirements);
149 StorageOperationStatus associateCapabilities = associateCapabilitiesToResource(nodeTypeVertex, nodeType, derivedResources);
150 if (associateCapabilities != StorageOperationStatus.OK) {
151 result = Either.right(associateCapabilities);
154 StorageOperationStatus associateCapabilitiesProps = associateCapabilitiesPropertiesToResource(nodeTypeVertex, nodeType, derivedResources);
155 if (associateCapabilitiesProps != StorageOperationStatus.OK) {
156 result = Either.right(associateCapabilitiesProps);
160 StorageOperationStatus associateInterfaces = associateInterfacesToResource(nodeTypeVertex, nodeType, derivedResources);
161 if (associateInterfaces != StorageOperationStatus.OK) {
162 result = Either.right(associateInterfaces);
166 StorageOperationStatus addAdditionalInformation = addAdditionalInformationToResource(nodeTypeVertex, nodeType, derivedResources);
167 if (addAdditionalInformation != StorageOperationStatus.OK) {
168 result = Either.right(addAdditionalInformation);
171 result = Either.left(nodeType);
176 private StorageOperationStatus associateInterfacesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
177 // Note : currently only one derived supported!!!!
178 Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.INTERFACE_ARTIFACTS);
179 if (dataFromDerived.isRight()) {
180 return dataFromDerived.right().value();
182 Map<String, InterfaceDataDefinition> interfacArtsAll = dataFromDerived.left().value();
184 Map<String, InterfaceDataDefinition> interfacArts = nodeType.getInterfaceArtifacts();
185 if (interfacArts != null) {
186 interfacArtsAll.putAll(interfacArts);
188 if (!interfacArtsAll.isEmpty()) {
189 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.INTERFACE_ARTIFACTS, EdgeLabelEnum.INTERFACE_ARTIFACTS, interfacArtsAll);
190 if (assosiateElementToData.isRight()) {
191 return assosiateElementToData.right().value();
194 return StorageOperationStatus.OK;
198 public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId, ComponentParametersView componentParametersView) {
200 Either<GraphVertex, StorageOperationStatus> componentByLabelAndId = getComponentByLabelAndId(uniqueId, ToscaElementTypeEnum.NodeType, JsonParseFlagEnum.ParseMetadata);
201 if (componentByLabelAndId.isRight()) {
202 return Either.right(componentByLabelAndId.right().value());
204 GraphVertex componentV = componentByLabelAndId.left().value();
206 return getToscaElement(componentV, componentParametersView);
210 // -------------------------------------------------------------
212 public Either<ToscaElement, StorageOperationStatus> getToscaElement(GraphVertex componentV, ComponentParametersView componentParametersView) {
213 NodeType toscaElement;
214 toscaElement = convertToComponent(componentV);
215 TitanOperationStatus status = null;
216 if (false == componentParametersView.isIgnoreUsers()) {
217 status = setCreatorFromGraph(componentV, toscaElement);
218 if (status != TitanOperationStatus.OK) {
219 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
222 status = setLastModifierFromGraph(componentV, toscaElement);
223 if (status != TitanOperationStatus.OK) {
224 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
228 if (false == componentParametersView.isIgnoreProperties()) {
229 status = setResourcePropertiesFromGraph(componentV, toscaElement);
230 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
231 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
235 if (false == componentParametersView.isIgnoreAttributesFrom()) {
236 status = setResourceAttributesFromGraph(componentV, toscaElement);
237 if (status != TitanOperationStatus.OK) {
238 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
242 if (false == componentParametersView.isIgnoreDerivedFrom()) {
243 status = setResourceDerivedFromGraph(componentV, toscaElement);
244 if (status != TitanOperationStatus.OK) {
245 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
249 if (false == componentParametersView.isIgnoreCategories()) {
250 status = setResourceCategoryFromGraph(componentV, toscaElement);
251 if (status != TitanOperationStatus.OK) {
252 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
255 if (false == componentParametersView.isIgnoreRequirements()) {
256 status = setResourceRequirementsFromGraph(componentV, toscaElement);
257 if (status != TitanOperationStatus.OK) {
258 log.error("Failed to set requirement of resource {}. status is {}", componentV.getUniqueId(), status);
259 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
262 if (false == componentParametersView.isIgnoreCapabilities()) {
263 status = setResourceCapabilitiesFromGraph(componentV, toscaElement);
264 if (status != TitanOperationStatus.OK) {
265 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
269 if (false == componentParametersView.isIgnoreArtifacts()) {
270 status = setArtifactsFromGraph(componentV, toscaElement);
271 if (status != TitanOperationStatus.OK) {
272 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
275 if (false == componentParametersView.isIgnoreAdditionalInformation()) {
276 status = setAdditionalInformationFromGraph(componentV, toscaElement);
277 if (status != TitanOperationStatus.OK) {
278 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
281 if (false == componentParametersView.isIgnoreInterfaces()) {
282 status = setInterfacesFromGraph(componentV, toscaElement);
283 if (status != TitanOperationStatus.OK) {
284 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
287 if (false == componentParametersView.isIgnoreAllVersions()) {
288 status = setAllVersions(componentV, toscaElement);
289 if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
290 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
294 if (false == componentParametersView.isIgnoreCapabiltyProperties()) {
295 status = setComponentCapPropertiesFromGraph(componentV, toscaElement);
296 if (status != TitanOperationStatus.OK) {
297 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
301 return Either.left(toscaElement);
304 private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
305 Either<Map<String, MapPropertiesDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
306 if (result.isLeft()) {
307 toscaElement.setCapabiltiesProperties(result.left().value());
309 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
310 return result.right().value();
313 return TitanOperationStatus.OK;
316 private TitanOperationStatus setInterfacesFromGraph(GraphVertex componentV, NodeType toscaElement) {
317 Either<Map<String, InterfaceDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.INTERFACE_ARTIFACTS);
318 if (result.isLeft()) {
319 toscaElement.setInterfaceArtifacts(result.left().value());
321 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
322 return result.right().value();
325 return TitanOperationStatus.OK;
328 protected <T extends ToscaElement> TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement) {
329 return setResourceCapabilitiesFromGraph(componentV, (NodeType) toscaElement);
332 private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
333 Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
334 if (result.isLeft()) {
335 toscaElement.setCapabilties(result.left().value());
337 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
338 return result.right().value();
341 return TitanOperationStatus.OK;
344 private TitanOperationStatus setResourceDerivedFromGraph(GraphVertex componentV, NodeType toscaElement) {
345 List<String> derivedFromList = new ArrayList<String>();
347 TitanOperationStatus listFromGraphStatus = findResourcesPathRecursively(componentV, derivedFromList);
348 if (TitanOperationStatus.OK != listFromGraphStatus) {
349 return listFromGraphStatus;
352 if (false == derivedFromList.isEmpty()) {
353 if (derivedFromList.size() > 1) {
354 List<String> lastDerivedFrom = new ArrayList<String>();
355 lastDerivedFrom.add(derivedFromList.get(1));
356 toscaElement.setDerivedFrom(lastDerivedFrom);
357 toscaElement.setDerivedList(derivedFromList);
359 toscaElement.setDerivedFrom(null);
360 toscaElement.setDerivedList(derivedFromList);
364 return TitanOperationStatus.OK;
367 protected TitanOperationStatus findResourcesPathRecursively(GraphVertex nodeTypeV, List<String> resourcesPathList) {
368 Either<GraphVertex, TitanOperationStatus> parentResourceRes = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
369 resourcesPathList.add((String) nodeTypeV.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
370 while (parentResourceRes.isLeft()) {
372 GraphVertex parent = parentResourceRes.left().value();
373 resourcesPathList.add((String) parent.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
374 parentResourceRes = titanDao.getChildVertex(parent, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
376 TitanOperationStatus operationStatus = parentResourceRes.right().value();
378 if (operationStatus != TitanOperationStatus.NOT_FOUND) {
379 return operationStatus;
381 return TitanOperationStatus.OK;
386 protected <T extends ToscaElement> TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) {
387 return setResourceRequirementsFromGraph(componentV, (NodeType) toscaElement);
390 private TitanOperationStatus setResourceRequirementsFromGraph(GraphVertex componentV, NodeType toscaElement) {
391 Either<Map<String, ListRequirementDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS);
392 if (result.isLeft()) {
393 toscaElement.setRequirements(result.left().value());
395 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
396 return result.right().value();
399 return TitanOperationStatus.OK;
402 private TitanOperationStatus setResourceAttributesFromGraph(GraphVertex componentV, NodeType toscaElement) {
403 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
404 if (result.isLeft()) {
405 toscaElement.setAttributes(result.left().value());
407 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
408 return result.right().value();
411 return TitanOperationStatus.OK;
414 private TitanOperationStatus setResourcePropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
415 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.PROPERTIES);
416 if (result.isLeft()) {
417 toscaElement.setProperties(result.left().value());
419 if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
420 return result.right().value();
423 return TitanOperationStatus.OK;
426 private StorageOperationStatus assosiateToDerived(GraphVertex nodeTypeVertex, List<GraphVertex> derivedResources) {
427 for (GraphVertex derivedV : derivedResources) {
428 TitanOperationStatus createEdge = titanDao.createEdge(nodeTypeVertex, derivedV, EdgeLabelEnum.DERIVED_FROM, null);
429 if (createEdge != TitanOperationStatus.OK) {
430 log.trace("Failed to associate resource {} to derived with id {}", nodeTypeVertex.getUniqueId(), derivedV.getUniqueId());
431 return DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge);
434 return StorageOperationStatus.OK;
437 private StorageOperationStatus addAdditionalInformationToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
438 // Note : currently only one derived supported!!!!
439 Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION);
440 if (dataFromDerived.isRight()) {
441 return dataFromDerived.right().value();
443 Map<String, AdditionalInfoParameterDataDefinition> addInformationAll = dataFromDerived.left().value();
445 Map<String, AdditionalInfoParameterDataDefinition> addInformation = nodeType.getAdditionalInformation();
446 if (addInformation != null) {
447 ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation);
449 if (!addInformationAll.isEmpty()) {
450 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, addInformationAll);
451 if (assosiateElementToData.isRight()) {
452 return assosiateElementToData.right().value();
455 return StorageOperationStatus.OK;
458 private StorageOperationStatus associateCapabilitiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
459 // Note : currently only one derived supported!!!!
460 Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES);
461 if (dataFromDerived.isRight()) {
462 return dataFromDerived.right().value();
464 Map<String, ListCapabilityDataDefinition> capabiltiesAll = dataFromDerived.left().value();
466 Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilties();
467 if (capabilties != null) {
468 if (capabiltiesAll == null) {
469 capabiltiesAll = new HashMap<>();
471 capabilties.values().forEach(l -> {
472 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
473 String uid = UniqueIdBuilder.buildCapabilityUid(nodeTypeVertex.getUniqueId(), p.getName());
478 ToscaDataDefinition.mergeDataMaps(capabiltiesAll, capabilties);
479 capabiltiesAll.values().forEach(l -> {
480 l.getListToscaDataDefinition().forEach(c -> {
481 List<String> capabilitySources = c.getCapabilitySources();
482 if (capabilitySources == null) {
483 capabilitySources = new ArrayList<>();
485 capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
486 c.setCapabilitySources(capabilitySources);
490 capabiltiesAll.values().forEach(l -> {
491 l.getListToscaDataDefinition().forEach(c -> {
492 List<String> capabilitySources = c.getCapabilitySources();
493 if (capabilitySources == null) {
494 capabilitySources = new ArrayList<>();
496 capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
497 c.setCapabilitySources(capabilitySources);
500 if (!capabiltiesAll.isEmpty()) {
501 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
502 if (assosiateElementToData.isRight()) {
503 return assosiateElementToData.right().value();
506 return StorageOperationStatus.OK;
509 private StorageOperationStatus associateRequirementsToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
510 // Note : currently only one derived supported!!!!
511 Either<Map<String, ListRequirementDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.REQUIREMENTS);
512 if (dataFromDerived.isRight()) {
513 return dataFromDerived.right().value();
515 Map<String, ListRequirementDataDefinition> requirementsAll = dataFromDerived.left().value();
517 Map<String, ListRequirementDataDefinition> requirements = nodeType.getRequirements();
518 if (requirements != null) {
519 if (requirementsAll == null) {
520 requirementsAll = new HashMap<>();
522 requirements.values().forEach(l -> {
523 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
524 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
529 ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements);
532 if (!requirementsAll.isEmpty()) {
533 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, EdgeLabelEnum.REQUIREMENTS, requirementsAll);
534 if (assosiateElementToData.isRight()) {
535 return assosiateElementToData.right().value();
538 return StorageOperationStatus.OK;
541 private StorageOperationStatus associateAttributesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
542 // Note : currently only one derived supported!!!!
543 Either<Map<String, PropertyDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ATTRIBUTES);
544 if (dataFromDerived.isRight()) {
545 return dataFromDerived.right().value();
547 Map<String, PropertyDataDefinition> attributesAll = dataFromDerived.left().value();
549 Map<String, PropertyDataDefinition> attributes = nodeType.getAttributes();
550 if (attributes != null) {
551 attributes.values().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
552 String uid = UniqueIdBuilder.buildAttributeUid(nodeTypeVertex.getUniqueId(), p.getName());
555 ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
557 if (!attributesAll.isEmpty()) {
558 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
559 if (assosiateElementToData.isRight()) {
560 return assosiateElementToData.right().value();
563 return StorageOperationStatus.OK;
566 // TODO get from derived
567 private StorageOperationStatus associateCapabilitiesPropertiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
568 // // Note : currently only one derived supported!!!!
569 Either<Map<String, MapPropertiesDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
570 if (dataFromDerived.isRight()) {
571 return dataFromDerived.right().value();
573 Map<String, MapPropertiesDataDefinition> propertiesAll = dataFromDerived.left().value();
574 Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabiltiesProperties();
575 if (capabiltiesProps != null) {
576 capabiltiesProps.values().forEach(l -> {
577 if (l.getMapToscaDataDefinition() != null && l.getMapToscaDataDefinition().values() != null) {
578 Collection<PropertyDataDefinition> mapToscaDataDefinition = l.getMapToscaDataDefinition().values();
579 mapToscaDataDefinition.stream().filter(p -> p != null && p.getUniqueId() == null).forEach(p -> {
580 String uid = UniqueIdBuilder.buildRequirementUid(nodeTypeVertex.getUniqueId(), p.getName());
585 ToscaDataDefinition.mergeDataMaps(propertiesAll, capabiltiesProps);
587 if (!propertiesAll.isEmpty()) {
588 Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, propertiesAll);
589 if (assosiateElementToData.isRight()) {
590 return assosiateElementToData.right().value();
593 return StorageOperationStatus.OK;
596 public Either<List<GraphVertex>, StorageOperationStatus> findDerivedResources(NodeType nodeType) {
598 List<GraphVertex> derivedResources = new ArrayList<GraphVertex>();
599 List<String> derivedFromResources = nodeType.getDerivedFrom();
600 if (derivedFromResources != null && false == derivedFromResources.isEmpty()) {
602 for (String parentResource : derivedFromResources) {
603 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = derivedResourceResolver.findDerivedResources(parentResource);
604 List<GraphVertex> resources = null;
605 if (getParentResources.isRight()) {
606 log.error("Cannot find parent resource by tosca resource name {} in the graph.", parentResource);
607 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
610 resources = getParentResources.left().value();
611 if (resources == null || resources.size() == 0) {
612 log.error("Cannot find parent resource by tosca name {} in the graph. resources size is empty", parentResource);
613 return Either.right(StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND);
615 if (resources.size() > 1) {
616 return handleMultipleParent(parentResource, derivedResources, resources);
618 GraphVertex parentResourceData = resources.get(0);
619 derivedResources.add(parentResourceData);
627 return Either.left(derivedResources);
630 Either<List<GraphVertex>, StorageOperationStatus> handleMultipleParent(String parentResource, List<GraphVertex> derivedResource, List<GraphVertex> fetchedDerivedResources) {
632 Either<List<GraphVertex>, StorageOperationStatus> result = Either.left(derivedResource);
634 fetchedDerivedResources.sort((d1, d2) -> {
635 return new Double(Double.parseDouble((String) d1.getMetadataProperty(GraphPropertyEnum.VERSION))).compareTo(Double.parseDouble((String) d2.getMetadataProperty(GraphPropertyEnum.VERSION)));
638 int actualHighestIndex = fetchedDerivedResources.size() - 1;
639 derivedResource.add(fetchedDerivedResources.get(actualHighestIndex));
640 fetchedDerivedResources.remove(actualHighestIndex);
642 StorageOperationStatus status = fixMultipleParent(fetchedDerivedResources);
643 if (status != StorageOperationStatus.OK) {
644 result = Either.right(status);
646 } catch (Exception e) {
647 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during handle multiple parent {}. Exception is {}", parentResource, e.getMessage());
648 result = Either.right(StorageOperationStatus.GENERAL_ERROR);
653 private StorageOperationStatus fixMultipleParent(List<GraphVertex> fetchedDerivedResources) {
654 StorageOperationStatus result = StorageOperationStatus.OK;
655 for (GraphVertex fetchedDerivedResource : fetchedDerivedResources) {
656 fetchedDerivedResource.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
657 Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(fetchedDerivedResource);
658 if (updateVertexRes.isRight()) {
659 TitanOperationStatus titatStatus = updateVertexRes.right().value();
660 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version of node type {} to false. Status is {}", fetchedDerivedResource.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME), titatStatus);
661 result = DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus);
668 private GraphVertex fillMetadata(GraphVertex nodeTypeVertex, NodeType nodeType) {
669 nodeTypeVertex.setLabel(VertexTypeEnum.NODE_TYPE);
671 fillCommonMetadata(nodeTypeVertex, nodeType);
673 return nodeTypeVertex;
677 public Either<ToscaElement, StorageOperationStatus> deleteToscaElement(GraphVertex toscaElementVertex) {
678 Either<ToscaElement, StorageOperationStatus> nodeType = getToscaElement(toscaElementVertex, new ComponentParametersView());
679 if (nodeType.isRight()) {
680 log.debug("Failed to fetch tosca element {} error {}", toscaElementVertex.getUniqueId(), nodeType.right().value());
683 TitanOperationStatus status = disassociateAndDeleteCommonElements(toscaElementVertex);
684 if (status != TitanOperationStatus.OK) {
685 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
687 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES);
688 if (status != TitanOperationStatus.OK) {
689 log.debug("Failed to disassociate capabilties for {} error {}", toscaElementVertex.getUniqueId(), status);
690 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
692 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
693 if (status != TitanOperationStatus.OK) {
694 log.debug("Failed to disassociate capabilties properties for {} error {}", toscaElementVertex.getUniqueId(), status);
695 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
697 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.REQUIREMENTS);
698 if (status != TitanOperationStatus.OK) {
699 log.debug("Failed to disassociate requirements for {} error {}", toscaElementVertex.getUniqueId(), status);
700 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
702 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ATTRIBUTES);
703 if (status != TitanOperationStatus.OK) {
704 log.debug("Failed to disassociate attributes for {} error {}", toscaElementVertex.getUniqueId(), status);
705 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
707 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.INTERFACE_ARTIFACTS);
708 if (status != TitanOperationStatus.OK) {
709 log.debug("Failed to disassociate interface artifacts for {} error {}", toscaElementVertex.getUniqueId(), status);
710 Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
712 toscaElementVertex.getVertex().remove();
713 log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
718 @SuppressWarnings("unchecked")
720 public Either<NodeType, StorageOperationStatus> createToscaElement(ToscaElement toscaElement) {
721 return createNodeType((NodeType) toscaElement);
725 protected <T extends ToscaElement> TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement) {
726 return setResourceCategoryFromGraph(vertexComponent, toscaElement);
730 protected <T extends ToscaElement> StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV) {
731 return validateResourceCategory(toscaElementToUpdate, elementV);
735 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) {
737 NodeType nodeType = (NodeType) toscaElementToUpdate;
738 List<GraphVertex> derivedResources = new ArrayList<>();
740 List<String> derivedFromResources = nodeType.getDerivedFrom();
742 // now supported only single derived from
743 if (derivedFromResources != null && !derivedFromResources.isEmpty() && derivedFromResources.get(0) != null) {
744 String firstDerived = derivedFromResources.get(0);
745 boolean derivedFromGenericType = null != nodeType.getDerivedFromGenericType();
746 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
747 if (childVertex.isRight()) {
748 TitanOperationStatus getchieldError = childVertex.right().value();
749 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchieldError);
750 return DaoStatusConverter.convertTitanStatusToStorageStatus(getchieldError);
752 GraphVertex firstDerivedInChain = childVertex.left().value();
754 String firstCurrentDerived = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME);
755 if (!firstDerived.equals(firstCurrentDerived) || derivedFromGenericType) {
757 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<GraphPropertyEnum, Object>();
758 propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
760 propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, firstDerived);
761 propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
763 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, JsonParseFlagEnum.NoParse);
765 if (getParentResources.isRight()) {
766 TitanOperationStatus error = getParentResources.right().value();
767 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch derived by criteria {}. error {} ", propertiesToMatch, error);
768 return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
771 GraphVertex newDerivedV = getParentResources.left().value().get(0);
772 return updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, newDerivedV, false);
775 return StorageOperationStatus.OK;
780 * @param toscaElementToUpdate
787 protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) {
788 Set<String> preDerivedChainIdList = new HashSet();
789 preDerivedChainIdList.add(preDerivedV.getUniqueId());
790 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(preDerivedV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
791 while (childVertex.isLeft()) {
792 GraphVertex currentChield = childVertex.left().value();
793 preDerivedChainIdList.add(currentChield.getUniqueId());
794 childVertex = titanDao.getChildVertex(currentChield, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
797 List<GraphVertex> derivedResources = new ArrayList<>();
798 derivedResources.add(newDerivedV);
799 StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType) toscaElementToUpdate, mergeValues, preDerivedChainIdList);
800 if (updateStatus != StorageOperationStatus.OK) {
801 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerivedV.getUniqueId(), updateStatus);
805 Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, preDerivedV, EdgeLabelEnum.DERIVED_FROM);
806 if (deleteEdge.isRight()) {
807 TitanOperationStatus deleteError = deleteEdge.right().value();
808 log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), preDerivedV.getUniqueId(), deleteError);
809 return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
812 titanDao.createEdge(nodeTypeV, newDerivedV, EdgeLabelEnum.DERIVED_FROM, new HashMap<>());
814 return StorageOperationStatus.OK;
817 private StorageOperationStatus associateDerivedDataByType(EdgeLabelEnum edgeLabel, GraphVertex nodeTypeV, NodeType nodeToUpdate, List<GraphVertex> newDerived) {
821 return associateCapabilitiesToResource(nodeTypeV, nodeToUpdate, newDerived);
823 return associateRequirementsToResource(nodeTypeV, nodeToUpdate, newDerived);
825 return associatePropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
827 return associateAttributesToResource(nodeTypeV, nodeToUpdate, newDerived);
828 case ADDITIONAL_INFORMATION:
829 return addAdditionalInformationToResource(nodeTypeV, nodeToUpdate, newDerived);
830 case CAPABILITIES_PROPERTIES:
831 return associateCapabilitiesPropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
833 return StorageOperationStatus.OK;
838 private StorageOperationStatus updateDataFromNewDerived(List<GraphVertex> newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set<String> preDerivedChainIdList) {
839 EnumSet<EdgeLabelEnum> edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION);
840 StorageOperationStatus status = null;
841 for (EdgeLabelEnum edge : edgeLabels) {
842 status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate, mergeValues, preDerivedChainIdList);
843 if (status != StorageOperationStatus.OK) {
851 private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(List<GraphVertex> newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set<String> preDerivedChainIdList) {
852 log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label);
853 Either<GraphVertex, TitanOperationStatus> dataFromGraph = getDataVertex(nodeTypeV, label);
854 if (dataFromGraph.isRight()) {
855 if (TitanOperationStatus.NOT_FOUND == dataFromGraph.right().value())
856 return associateDerivedDataByType(label, nodeTypeV, nodeElement, newDerivedList);
857 return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
859 GraphVertex dataV = dataFromGraph.left().value();
861 Map<String, T> mapFromGraph = (Map<String, T>) dataV.getJson();
862 Map<String, T> valuesFrmPrev = null;
863 if (isSimpleHierarchy(label)) {
865 valuesFrmPrev = mapFromGraph.entrySet().stream().filter(e -> e.getValue().getOwnerId() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
867 mapFromGraph.entrySet().removeIf(e -> preDerivedChainIdList.contains(e.getValue().getOwnerId()));
869 final Map<String, T> valuesFrmPrevFinal = new HashMap<>();
870 mapFromGraph.entrySet().stream().forEach(e -> {
871 T value = e.getValue();
872 value = ToscaDataDefinition.removeAndCollectByOwnerId(value, preDerivedChainIdList);
873 valuesFrmPrevFinal.put(e.getKey(), value);
875 valuesFrmPrev = valuesFrmPrevFinal;
876 mapFromGraph.entrySet().removeIf(e->e.getValue().isEmpty());
879 Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label);
880 if (dataFromDerived.isRight()) {
881 return dataFromDerived.right().value();
883 Map<String, T> dataFromDerivedAll = dataFromDerived.left().value();
885 Either<Map<String, T>, String> merged = ToscaDataDefinition.mergeDataMaps(dataFromDerivedAll, mapFromGraph);
886 if (merged.isRight()) {
887 log.debug("property {} cannot be overriden", merged.right().value());
888 return StorageOperationStatus.INVALID_PROPERTY;
890 if (mergeValues && valuesFrmPrev != null) {
891 valuesFrmPrev.entrySet().forEach(e -> {
892 T newData = merged.left().value().get(e.getKey());
893 if (newData != null) {
894 if (isSimpleHierarchy(label)) {
895 e.getValue().mergeFunction(newData, true);
897 e.getValue().updateIfExist(newData, true);
902 dataV.setJson(dataFromDerivedAll);
903 Either<GraphVertex, TitanOperationStatus> updateDataV = updateOrCopyOnUpdate(dataV, nodeTypeV, label);
904 if (updateDataV.isRight()) {
905 return DaoStatusConverter.convertTitanStatusToStorageStatus(updateDataV.right().value());
907 return StorageOperationStatus.OK;
910 private boolean isSimpleHierarchy(EdgeLabelEnum label) {
914 case ADDITIONAL_INFORMATION:
925 public <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) {
926 fillMetadata(elementV, (NodeType) toscaElementToUpdate);
929 public Either<ToscaElement, StorageOperationStatus> shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) {
930 NodeType nodeType = (NodeType) toscaElementToUpdate;
932 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
933 if (childVertex.isRight()) {
934 TitanOperationStatus getchildError = childVertex.right().value();
935 if (getchildError == TitanOperationStatus.NOT_FOUND) {
936 log.debug("derived resource for element {} not found", nodeTypeV.getUniqueId());
937 return Either.right(StorageOperationStatus.OK);
940 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchildError);
941 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getchildError));
943 GraphVertex firstDerivedInChain = childVertex.left().value();
945 String currentVersion = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.VERSION);
947 Map<GraphPropertyEnum, Object> props = new HashMap<>();
948 props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeType.getDerivedFrom().get(0));
949 props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
950 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
952 Map<GraphPropertyEnum, Object> propsHasNot = new HashMap<>();
953 propsHasNot.put(GraphPropertyEnum.IS_DELETED, true);
954 Either<List<GraphVertex>, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, props, propsHasNot, JsonParseFlagEnum.NoParse);
955 if (byCriteria.isRight()) {
956 log.debug("Failed to fetch derived by props {} error {}", props, byCriteria.right().value());
957 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
959 List<GraphVertex> lastDerived = byCriteria.left().value();
960 // now supported only one derived!!! Change in future!(Evg)
961 GraphVertex derivedFromHighest = lastDerived.get(0);
962 String highestVersion = (String) derivedFromHighest.getMetadataProperty(GraphPropertyEnum.VERSION);
963 if (!highestVersion.equals(currentVersion)) {
965 // need to update to latest version of derived from
966 StorageOperationStatus updateDerived = updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, derivedFromHighest, true);
968 if (updateDerived != StorageOperationStatus.OK) {
969 log.debug("Failed to update {} to highest derived {} from error {}", nodeTypeV.getUniqueId(), derivedFromHighest.getUniqueId(), updateDerived);
970 return Either.right(updateDerived);
972 return getToscaElement(nodeTypeV.getUniqueId(), new ComponentParametersView());
974 // no version changes
975 return Either.right(StorageOperationStatus.OK);