Fix - Blockstorage and Compute in VF linking
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / operations / NodeTypeOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.jsontitan.operations;
22
23 import fj.data.Either;
24
25 import org.apache.tinkerpop.gremlin.structure.Direction;
26 import org.apache.tinkerpop.gremlin.structure.Edge;
27 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
28 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
29 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
30 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
31 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
32 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
33 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
34 import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
37 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
39 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
40 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
41 import org.openecomp.sdc.be.model.ComponentParametersView;
42 import org.openecomp.sdc.be.model.DerivedNodeTypeResolver;
43 import org.openecomp.sdc.be.model.LifecycleStateEnum;
44 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
45 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
46 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
47 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
48 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
49 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
50 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
51 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.annotation.Qualifier;
55
56 import java.util.ArrayList;
57 import java.util.Collection;
58 import java.util.EnumSet;
59 import java.util.HashMap;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.regex.Pattern;
63
64 @org.springframework.stereotype.Component("node-type-operation")
65 public class NodeTypeOperation extends ToscaElementOperation {
66         public static Pattern uuidNewVersion = Pattern.compile("^\\d{1,}.1");
67         public static Pattern uuidNormativeNewVersion = Pattern.compile("^\\d{1,}.0");
68
69         private static Logger log = LoggerFactory.getLogger(NodeTypeOperation.class.getName());
70
71         private DerivedNodeTypeResolver derivedResourceResolver;
72
73         public NodeTypeOperation(@Qualifier("derived-resource-resolver") DerivedNodeTypeResolver derivedNodeTypeResolver) {
74                 this.derivedResourceResolver = derivedNodeTypeResolver;
75         }
76
77         public Either<NodeType, StorageOperationStatus> createNodeType(NodeType nodeType) {
78
79                 Either<NodeType, StorageOperationStatus> result = null;
80
81                 nodeType.generateUUID();
82
83                 nodeType = getResourceMetaDataFromResource(nodeType);
84                 String resourceUniqueId = nodeType.getUniqueId();
85                 if (resourceUniqueId == null) {
86                         resourceUniqueId = UniqueIdBuilder.buildResourceUniqueId();
87                         nodeType.setUniqueId(resourceUniqueId);
88                 }
89
90                 // get derived from resources
91                 List<GraphVertex> derivedResources = null;
92                 Either<List<GraphVertex>, StorageOperationStatus> derivedResourcesResult = findDerivedResources(nodeType);
93                 if (derivedResourcesResult.isRight()) {
94                         result = Either.right(derivedResourcesResult.right().value());
95                         return result;
96                 } else {
97                         derivedResources = derivedResourcesResult.left().value();
98                 }
99
100                 GraphVertex nodeTypeVertex = new GraphVertex(VertexTypeEnum.NODE_TYPE);
101                 fillToscaElementVertexData(nodeTypeVertex, nodeType, JsonParseFlagEnum.ParseAll);
102
103                 Either<GraphVertex, TitanOperationStatus> createdVertex = titanDao.createVertex(nodeTypeVertex);
104                 if (createdVertex.isRight()) {
105                         TitanOperationStatus status = createdVertex.right().value();
106                         log.error("Error returned after creating resource data node {}. status returned is ", nodeTypeVertex, status);
107                         result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
108                         return result;
109                 }
110                 nodeTypeVertex = createdVertex.left().value();
111
112                 StorageOperationStatus assosiateCommon = assosiateCommonForToscaElement(nodeTypeVertex, nodeType, derivedResources);
113                 if (assosiateCommon != StorageOperationStatus.OK) {
114                         result = Either.right(assosiateCommon);
115                         return result;
116                 }
117
118                 StorageOperationStatus associateDerived = assosiateToDerived(nodeTypeVertex, derivedResources);
119                 if (associateDerived != StorageOperationStatus.OK) {
120                         result = Either.right(associateDerived);
121                         return result;
122                 }
123                 StorageOperationStatus associateCategory = assosiateResourceMetadataToCategory(nodeTypeVertex, nodeType);
124                 if (associateCategory != StorageOperationStatus.OK) {
125                         result = Either.right(associateCategory);
126                         return result;
127                 }
128
129                 StorageOperationStatus associateAttributes = associateAttributesToResource(nodeTypeVertex, nodeType, derivedResources);
130                 if (associateAttributes != StorageOperationStatus.OK) {
131                         result = Either.right(associateAttributes);
132                         return result;
133                 }
134
135                 StorageOperationStatus associateRequirements = associateRequirementsToResource(nodeTypeVertex, nodeType, derivedResources);
136                 if (associateRequirements != StorageOperationStatus.OK) {
137                         result = Either.right(associateRequirements);
138                         return result;
139                 }
140
141                 StorageOperationStatus associateCapabilities = associateCapabilitiesToResource(nodeTypeVertex, nodeType, derivedResources);
142                 if (associateCapabilities != StorageOperationStatus.OK) {
143                         result = Either.right(associateCapabilities);
144                         return result;
145                 }
146                 StorageOperationStatus associateCapabilitiesProps = associateCapabilitiesPropertiesToResource(nodeTypeVertex, nodeType, derivedResources);
147                 if (associateCapabilitiesProps != StorageOperationStatus.OK) {
148                         result = Either.right(associateCapabilitiesProps);
149                         return result;
150                 }
151
152                 StorageOperationStatus associateInterfaces = associateInterfacesToResource(nodeTypeVertex, nodeType, derivedResources);
153                 if (associateInterfaces != StorageOperationStatus.OK) {
154                         result = Either.right(associateInterfaces);
155                         return result;
156                 }
157
158                 StorageOperationStatus addAdditionalInformation = addAdditionalInformationToResource(nodeTypeVertex, nodeType, derivedResources);
159                 if (addAdditionalInformation != StorageOperationStatus.OK) {
160                         result = Either.right(addAdditionalInformation);
161                         return result;
162                 }
163                 result = Either.left(nodeType);
164                 return result;
165
166         }
167
168         private StorageOperationStatus associateInterfacesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
169                 // Note : currently only one derived supported!!!!
170                 Either<Map<String, InterfaceDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.INTERFACE_ARTIFACTS);
171                 if (dataFromDerived.isRight()) {
172                         return dataFromDerived.right().value();
173                 }
174                 Map<String, InterfaceDataDefinition> interfacArtsAll = dataFromDerived.left().value();
175
176                 Map<String, InterfaceDataDefinition> interfacArts = nodeType.getInterfaceArtifacts();
177                 if (interfacArts != null) {
178                         interfacArtsAll.putAll(interfacArts);
179                 }
180                 if (!interfacArtsAll.isEmpty()) {
181                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.INTERFACE_ARTIFACTS, EdgeLabelEnum.INTERFACE_ARTIFACTS, interfacArtsAll);
182                         if (assosiateElementToData.isRight()) {
183                                 return assosiateElementToData.right().value();
184                         }
185                 }
186                 return StorageOperationStatus.OK;
187         }
188
189         @Override
190         public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId, ComponentParametersView componentParametersView) {
191
192                 Either<GraphVertex, StorageOperationStatus> componentByLabelAndId = getComponentByLabelAndId(uniqueId, ToscaElementTypeEnum.NodeType, JsonParseFlagEnum.ParseMetadata);
193                 if (componentByLabelAndId.isRight()) {
194                         return Either.right(componentByLabelAndId.right().value());
195                 }
196                 GraphVertex componentV = componentByLabelAndId.left().value();
197
198                 return getToscaElement(componentV, componentParametersView);
199
200         }
201
202         // -------------------------------------------------------------
203         @Override
204         public Either<ToscaElement, StorageOperationStatus> getToscaElement(GraphVertex componentV, ComponentParametersView componentParametersView) {
205                 NodeType toscaElement;
206                 toscaElement = convertToComponent(componentV);
207                 TitanOperationStatus status = null;
208                 if (false == componentParametersView.isIgnoreUsers()) {
209                         status = setCreatorFromGraph(componentV, toscaElement);
210                         if (status != TitanOperationStatus.OK) {
211                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
212                         }
213
214                         status = setLastModifierFromGraph(componentV, toscaElement);
215                         if (status != TitanOperationStatus.OK) {
216                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
217                         }
218                 }
219
220                 if (false == componentParametersView.isIgnoreProperties()) {
221                         status = setResourcePropertiesFromGraph(componentV, toscaElement);
222                         if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
223                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
224                         }
225                 }
226
227                 if (false == componentParametersView.isIgnoreAttributesFrom()) {
228                         status = setResourceAttributesFromGraph(componentV, toscaElement);
229                         if (status != TitanOperationStatus.OK) {
230                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
231                         }
232                 }
233
234                 if (false == componentParametersView.isIgnoreDerivedFrom()) {
235                         status = setResourceDerivedFromGraph(componentV, toscaElement);
236                         if (status != TitanOperationStatus.OK) {
237                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
238                         }
239                 }
240
241                 if (false == componentParametersView.isIgnoreCategories()) {
242                         status = setResourceCategoryFromGraph(componentV, toscaElement);
243                         if (status != TitanOperationStatus.OK) {
244                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
245                         }
246                 }
247                 if (false == componentParametersView.isIgnoreRequirements()) {
248                         status = setResourceRequirementsFromGraph(componentV, toscaElement);
249                         if (status != TitanOperationStatus.OK) {
250                                 log.error("Failed to set requirement of resource {}. status is {}", componentV.getUniqueId(), status);
251                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
252                         }
253                 }
254                 if (false == componentParametersView.isIgnoreCapabilities()) {
255                         status = setResourceCapabilitiesFromGraph(componentV, toscaElement);
256                         if (status != TitanOperationStatus.OK) {
257                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
258                         }
259                 }
260
261                 if (false == componentParametersView.isIgnoreArtifacts()) {
262                         status = setArtifactsFromGraph(componentV, toscaElement);
263                         if (status != TitanOperationStatus.OK) {
264                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
265                         }
266                 }
267                 if (false == componentParametersView.isIgnoreAdditionalInformation()) {
268                         status = setAdditionalInformationFromGraph(componentV, toscaElement);
269                         if (status != TitanOperationStatus.OK) {
270                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
271                         }
272                 }
273                 if (false == componentParametersView.isIgnoreInterfaces()) {
274                         status = setInterfacesFromGraph(componentV, toscaElement);
275                         if (status != TitanOperationStatus.OK) {
276                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
277                         }
278                 }
279                 if (false == componentParametersView.isIgnoreAllVersions()) {
280                         status = setAllVersions(componentV, toscaElement);
281                         if (status != TitanOperationStatus.OK && status != TitanOperationStatus.NOT_FOUND) {
282                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
283                         }
284                 }
285
286                 if (false == componentParametersView.isIgnoreCapabiltyProperties()) {
287                         status = setComponentCapPropertiesFromGraph(componentV, toscaElement);
288                         if (status != TitanOperationStatus.OK) {
289                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
290
291                         }
292                 }
293                 return Either.left(toscaElement);
294         }
295
296         private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
297                 Either<Map<String, MapPropertiesDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
298                 if (result.isLeft()) {
299                         toscaElement.setCapabiltiesProperties(result.left().value());
300                 } else {
301                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
302                                 return result.right().value();
303                         }
304                 }
305                 return TitanOperationStatus.OK;
306         }
307
308         private TitanOperationStatus setInterfacesFromGraph(GraphVertex componentV, NodeType toscaElement) {
309                 Either<Map<String, InterfaceDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.INTERFACE_ARTIFACTS);
310                 if (result.isLeft()) {
311                         toscaElement.setInterfaceArtifacts(result.left().value());
312                 } else {
313                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
314                                 return result.right().value();
315                         }
316                 }
317                 return TitanOperationStatus.OK;
318         }
319
320         protected <T extends ToscaElement> TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement) {
321                 return setResourceCapabilitiesFromGraph(componentV, (NodeType) toscaElement);
322         }
323
324         private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
325                 Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
326                 if (result.isLeft()) {
327                         toscaElement.setCapabilties(result.left().value());
328                 } else {
329                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
330                                 return result.right().value();
331                         }
332                 }
333                 return TitanOperationStatus.OK;
334         }
335
336         private TitanOperationStatus setResourceDerivedFromGraph(GraphVertex componentV, NodeType toscaElement) {
337                 List<String> derivedFromList = new ArrayList<String>();
338
339                 TitanOperationStatus listFromGraphStatus = findResourcesPathRecursively(componentV, derivedFromList);
340                 if (TitanOperationStatus.OK != listFromGraphStatus) {
341                         return listFromGraphStatus;
342                 }
343
344                 if (false == derivedFromList.isEmpty()) {
345                         if (derivedFromList.size() > 1) {
346                                 List<String> lastDerivedFrom = new ArrayList<String>();
347                                 lastDerivedFrom.add(derivedFromList.get(1));
348                                 toscaElement.setDerivedFrom(lastDerivedFrom);
349                                 toscaElement.setDerivedList(derivedFromList);
350                         } else {
351                                 toscaElement.setDerivedFrom(null);
352                                 toscaElement.setDerivedList(derivedFromList);
353                         }
354
355                 }
356                 return TitanOperationStatus.OK;
357         }
358
359         protected TitanOperationStatus findResourcesPathRecursively(GraphVertex nodeTypeV, List<String> resourcesPathList) {
360                 Either<GraphVertex, TitanOperationStatus> parentResourceRes = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
361                 resourcesPathList.add((String) nodeTypeV.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
362                 while (parentResourceRes.isLeft()) {
363
364                         GraphVertex parent = parentResourceRes.left().value();
365                         resourcesPathList.add((String) parent.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME));
366                         parentResourceRes = titanDao.getChildVertex(parent, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
367                 }
368                 TitanOperationStatus operationStatus = parentResourceRes.right().value();
369
370                 if (operationStatus != TitanOperationStatus.NOT_FOUND) {
371                         return operationStatus;
372                 } else {
373                         return TitanOperationStatus.OK;
374                 }
375
376         }
377
378         protected <T extends ToscaElement> TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) {
379                 return setResourceRequirementsFromGraph(componentV, (NodeType) toscaElement);
380         }
381
382         private TitanOperationStatus setResourceRequirementsFromGraph(GraphVertex componentV, NodeType toscaElement) {
383                 Either<Map<String, ListRequirementDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS);
384                 if (result.isLeft()) {
385                         toscaElement.setRequirements(result.left().value());
386                 } else {
387                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
388                                 return result.right().value();
389                         }
390                 }
391                 return TitanOperationStatus.OK;
392         }
393
394         private TitanOperationStatus setResourceAttributesFromGraph(GraphVertex componentV, NodeType toscaElement) {
395                 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ATTRIBUTES);
396                 if (result.isLeft()) {
397                         toscaElement.setAttributes(result.left().value());
398                 } else {
399                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
400                                 return result.right().value();
401                         }
402                 }
403                 return TitanOperationStatus.OK;
404         }
405
406         private TitanOperationStatus setResourcePropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
407                 Either<Map<String, PropertyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.PROPERTIES);
408                 if (result.isLeft()) {
409                         toscaElement.setProperties(result.left().value());
410                 } else {
411                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
412                                 return result.right().value();
413                         }
414                 }
415                 return TitanOperationStatus.OK;
416         }
417
418         private StorageOperationStatus assosiateToDerived(GraphVertex nodeTypeVertex, List<GraphVertex> derivedResources) {
419                 for (GraphVertex derivedV : derivedResources) {
420                         TitanOperationStatus createEdge = titanDao.createEdge(nodeTypeVertex, derivedV, EdgeLabelEnum.DERIVED_FROM, null);
421                         if (createEdge != TitanOperationStatus.OK) {
422                                 log.trace("Failed to associate resource {} to derived with id {}", nodeTypeVertex.getUniqueId(), derivedV.getUniqueId());
423                                 return DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge);
424                         }
425                 }
426                 return StorageOperationStatus.OK;
427         }
428
429         private StorageOperationStatus addAdditionalInformationToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
430                 // Note : currently only one derived supported!!!!
431                 Either<Map<String, AdditionalInfoParameterDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.ADDITIONAL_INFORMATION);
432                 if (dataFromDerived.isRight()) {
433                         return dataFromDerived.right().value();
434                 }
435                 Map<String, AdditionalInfoParameterDataDefinition> addInformationAll = dataFromDerived.left().value();
436
437                 Map<String, AdditionalInfoParameterDataDefinition> addInformation = nodeType.getAdditionalInformation();
438                 if (addInformation != null) {
439                         ToscaDataDefinition.mergeDataMaps(addInformationAll, addInformation);
440                 }
441                 if (!addInformationAll.isEmpty()) {
442                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, addInformationAll);
443                         if (assosiateElementToData.isRight()) {
444                                 return assosiateElementToData.right().value();
445                         }
446                 }
447                 return StorageOperationStatus.OK;
448         }
449
450         private StorageOperationStatus associateCapabilitiesToResource(GraphVertex nodeTypeVertex, NodeType nodeType, List<GraphVertex> derivedResources) {
451                 // Note : currently only one derived supported!!!!
452                 Either<Map<String, ListCapabilityDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.CAPABILITIES);
453                 if (dataFromDerived.isRight()) {
454                         return dataFromDerived.right().value();
455                 }
456                 Map<String, ListCapabilityDataDefinition> capabiltiesAll = dataFromDerived.left().value();
457
458                 Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilties();
459                 if (capabilties != null) {
460                         if (capabiltiesAll == null) {
461                                 capabiltiesAll = new HashMap<>();
462                         }
463                         capabilties.values().forEach(l -> {
464                                 l.getListToscaDataDefinition().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
465                                         String uid = UniqueIdBuilder.buildCapabilityUid(nodeTypeVertex.getUniqueId(), p.getName());
466                                         p.setUniqueId(uid);
467                                 });
468                         });
469
470                         ToscaDataDefinition.mergeDataMaps(capabiltiesAll, capabilties);
471                 }
472                 
473                 capabiltiesAll.values().forEach(l -> {
474             l.getListToscaDataDefinition().forEach(c -> {
475                   List<String> capabilitySources = c.getCapabilitySources();
476                   if ( capabilitySources == null ){
477                         capabilitySources = new ArrayList<>();
478                   }
479                   capabilitySources.add((String) nodeType.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
480                   c.setCapabilitySources(capabilitySources);
481             });
482       });
483
484                 
485                 if (!capabiltiesAll.isEmpty()) {
486                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
487                         if (assosiateElementToData.isRight()) {
488                                 return assosiateElementToData.right().value();
489                         }
490                 }
491                 return StorageOperationStatus.OK;
492         }
493
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();
499                 }
500                 Map<String, ListRequirementDataDefinition> requirementsAll = dataFromDerived.left().value();
501
502                 Map<String, ListRequirementDataDefinition> requirements = nodeType.getRequirements();
503                 if (requirements != null) {
504                         if (requirementsAll == null) {
505                                 requirementsAll = new HashMap<>();
506                         }
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());
510                                         p.setUniqueId(uid);
511                                 });
512                         });
513                         
514                         ToscaDataDefinition.mergeDataMaps(requirementsAll, requirements);
515
516                 }
517                 if (!requirementsAll.isEmpty()) {
518                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, EdgeLabelEnum.REQUIREMENTS, requirementsAll);
519                         if (assosiateElementToData.isRight()) {
520                                 return assosiateElementToData.right().value();
521                         }
522                 }
523                 return StorageOperationStatus.OK;
524         }
525
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();
531                 }
532                 Map<String, PropertyDataDefinition> attributesAll = dataFromDerived.left().value();
533
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());
538                                 p.setUniqueId(uid);
539                         });
540                         ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
541                 }
542                 if (!attributesAll.isEmpty()) {
543                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
544                         if (assosiateElementToData.isRight()) {
545                                 return assosiateElementToData.right().value();
546                         }
547                 }
548                 return StorageOperationStatus.OK;
549         }
550
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();
557                 }
558                 Map<String, MapPropertiesDataDefinition> propertiesAll = dataFromDerived.left().value();
559                 Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabiltiesProperties();
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());
566                                                 p.setUniqueId(uid);
567                                         });
568                                 }
569                         });
570                         ToscaDataDefinition.mergeDataMaps(propertiesAll, capabiltiesProps);
571                 }
572                 if (!propertiesAll.isEmpty()) {
573                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, propertiesAll);
574                         if (assosiateElementToData.isRight()) {
575                                 return assosiateElementToData.right().value();
576                         }
577                 }
578                 return StorageOperationStatus.OK;
579         }
580
581         public Either<List<GraphVertex>, StorageOperationStatus> findDerivedResources(NodeType nodeType) {
582
583                 List<GraphVertex> derivedResources = new ArrayList<GraphVertex>();
584                 List<String> derivedFromResources = nodeType.getDerivedFrom();
585                 if (derivedFromResources != null && false == derivedFromResources.isEmpty()) {
586
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);
593
594                                 } else {
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);
599                                         } else {
600                                                 if (resources.size() > 1) {
601                                                         log.error("Multiple parent resources called {} found in the graph.", parentResource);
602                                                         return Either.right(StorageOperationStatus.MULTIPLE_PARENT_RESOURCE_FOUND);
603                                                 }
604                                                 GraphVertex parentResourceData = resources.get(0);
605                                                 derivedResources.add(parentResourceData);
606                                         }
607
608                                 }
609
610                         }
611                 }
612                 return Either.left(derivedResources);
613         }
614
615         private GraphVertex fillMetadata(GraphVertex nodeTypeVertex, NodeType nodeType) {
616                 nodeTypeVertex.setLabel(VertexTypeEnum.NODE_TYPE);
617
618                 fillCommonMetadata(nodeTypeVertex, nodeType);
619
620                 return nodeTypeVertex;
621         }
622
623         @Override
624         public Either<ToscaElement, StorageOperationStatus> deleteToscaElement(GraphVertex toscaElementVertex) {
625                 Either<ToscaElement, StorageOperationStatus> nodeType = getToscaElement(toscaElementVertex, new ComponentParametersView());
626                 if (nodeType.isRight()) {
627                         log.debug("Failed to fetch tosca element {} error {}", toscaElementVertex.getUniqueId(), nodeType.right().value());
628                         return nodeType;
629                 }
630                 TitanOperationStatus status = disassociateAndDeleteCommonElements(toscaElementVertex);
631                 if (status != TitanOperationStatus.OK) {
632                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
633                 }
634                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES);
635                 if (status != TitanOperationStatus.OK) {
636                         log.debug("Failed to disassociate capabilties for {} error {}", toscaElementVertex.getUniqueId(), status);
637                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
638                 }
639                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
640                 if (status != TitanOperationStatus.OK) {
641                         log.debug("Failed to disassociate capabilties properties for {} error {}", toscaElementVertex.getUniqueId(), status);
642                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
643                 }
644                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.REQUIREMENTS);
645                 if (status != TitanOperationStatus.OK) {
646                         log.debug("Failed to disassociate requirements for {} error {}", toscaElementVertex.getUniqueId(), status);
647                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
648                 }
649                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ATTRIBUTES);
650                 if (status != TitanOperationStatus.OK) {
651                         log.debug("Failed to disassociate attributes for {} error {}", toscaElementVertex.getUniqueId(), status);
652                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
653                 }
654                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.INTERFACE_ARTIFACTS);
655                 if (status != TitanOperationStatus.OK) {
656                         log.debug("Failed to disassociate interface artifacts for {} error {}", toscaElementVertex.getUniqueId(), status);
657                         Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
658                 }
659                 toscaElementVertex.getVertex().remove();
660                 log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
661
662                 return nodeType;
663         }
664
665         @SuppressWarnings("unchecked")
666         @Override
667         public Either<NodeType, StorageOperationStatus> createToscaElement(ToscaElement toscaElement) {
668                 return createNodeType((NodeType) toscaElement);
669         }
670
671         @Override
672         protected <T extends ToscaElement> TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement) {
673                 return setResourceCategoryFromGraph(vertexComponent, toscaElement);
674         }
675
676         @Override
677         protected <T extends ToscaElement> StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV) {
678                 return validateResourceCategory(toscaElementToUpdate, elementV);
679         }
680
681         @Override
682         protected <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV) {
683
684                 NodeType nodeType = (NodeType) toscaElementToUpdate;
685                 List<GraphVertex> derivedResources = new ArrayList<>();
686
687                 List<String> derivedFromResources = nodeType.getDerivedFrom();
688
689                 // now supported only single derived from
690                 if (derivedFromResources != null && !derivedFromResources.isEmpty() && derivedFromResources.get(0) != null) {
691                         String firstDerived = derivedFromResources.get(0);
692                         boolean derivedFromGenericType = null != nodeType.getDerivedFromGenericType();
693                         Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse);
694                         if (childVertex.isRight()) {
695                                 TitanOperationStatus getchieldError = childVertex.right().value();
696                                 log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchieldError);
697                                 return DaoStatusConverter.convertTitanStatusToStorageStatus(getchieldError);
698                         }
699                         GraphVertex firstDerivedInChain = childVertex.left().value();
700
701                         String firstCurrentDerived = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME);
702                         if (!firstDerived.equals(firstCurrentDerived) || derivedFromGenericType) {
703
704                                 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<GraphPropertyEnum, Object>();
705                                 propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
706
707                                 propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, firstDerived);
708                                 propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
709
710                                 Either<List<GraphVertex>, TitanOperationStatus> getParentResources = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, JsonParseFlagEnum.NoParse);
711
712                                 if (getParentResources.isRight()) {
713                                         TitanOperationStatus error = getParentResources.right().value();
714                                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch derived by criteria {}. error {} ", propertiesToMatch, error);
715                                         return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
716                                 }
717                                 // must be only one
718                                 GraphVertex newDerived = getParentResources.left().value().get(0);
719                                 derivedResources.add(newDerived);
720                                 StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType)toscaElementToUpdate);
721                                 if (updateStatus != StorageOperationStatus.OK) {
722                                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerived.getUniqueId(), updateStatus);
723                                         return updateStatus;
724                                 }
725
726                                 Either<Edge, TitanOperationStatus> deleteEdge = titanDao.deleteEdge(nodeTypeV, firstDerivedInChain, EdgeLabelEnum.DERIVED_FROM);
727                                 if (deleteEdge.isRight()) {
728                                         TitanOperationStatus deleteError = deleteEdge.right().value();
729                                         log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), firstDerivedInChain.getUniqueId(), deleteError);
730                                         return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError);
731                                 }
732
733                                 titanDao.createEdge(nodeTypeV, newDerived, EdgeLabelEnum.DERIVED_FROM, new HashMap<>());
734                         }
735                 }
736
737                 return StorageOperationStatus.OK;
738         }
739         
740         private StorageOperationStatus associateDerivedDataByType(EdgeLabelEnum edgeLabel, GraphVertex nodeTypeV, NodeType nodeToUpdate, List<GraphVertex> newDerived) {
741                 
742                 switch (edgeLabel) {
743                 case CAPABILITIES:
744                         return associateCapabilitiesToResource(nodeTypeV, nodeToUpdate, newDerived);
745                 case REQUIREMENTS:
746                         return associateRequirementsToResource(nodeTypeV, nodeToUpdate, newDerived);
747                 case PROPERTIES:
748                         return associatePropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
749                 case ATTRIBUTES:
750                         return associateAttributesToResource(nodeTypeV, nodeToUpdate, newDerived);
751                 case ADDITIONAL_INFORMATION:
752                         return addAdditionalInformationToResource(nodeTypeV, nodeToUpdate, newDerived);
753                 case CAPABILITIES_PROPERTIES:
754                         return associateCapabilitiesPropertiesToResource(nodeTypeV, nodeToUpdate, newDerived);
755                 default:
756                         return StorageOperationStatus.OK;
757                 }
758
759         }
760
761         private StorageOperationStatus updateDataFromNewDerived(List<GraphVertex> newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate) {    
762                 EnumSet<EdgeLabelEnum> edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION);
763                 StorageOperationStatus status = null;
764                 for (EdgeLabelEnum edge : edgeLabels){
765                         status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate);
766                         if (status != StorageOperationStatus.OK) {
767                                 break;
768                         }
769                 }
770                 return status;
771                 
772         }
773
774         private <T extends ToscaDataDefinition> StorageOperationStatus updateDataByType(List<GraphVertex> newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement) {
775                 log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label);
776                 Either<GraphVertex, TitanOperationStatus> dataFromGraph = getDataVertex(nodeTypeV, label);
777                 if (dataFromGraph.isRight()) {
778                         if (TitanOperationStatus.NOT_FOUND == dataFromGraph.right().value())
779                                 return associateDerivedDataByType(label, nodeTypeV, nodeElement, newDerivedList);
780                         return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
781                 }
782                 GraphVertex dataV = dataFromGraph.left().value();
783
784                 Map<String, T> mapFromGraph = (Map<String, T>) dataV.getJson();
785                 mapFromGraph.entrySet().removeIf(e -> e.getValue().getOwnerId() != null);
786
787                 
788                 Either<Map<String, T>, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label);
789                 if (dataFromDerived.isRight()) {
790                         return dataFromDerived.right().value();
791                 }
792                 Map<String, T> dataFromDerivedAll = dataFromDerived.left().value();
793                 
794                 Either<Map<String, T>, String> merged = ToscaDataDefinition.mergeDataMaps(dataFromDerivedAll, mapFromGraph);
795                 if(merged.isRight()){
796                         log.debug("property {} cannot be overriden", merged.right().value());
797                         return StorageOperationStatus.INVALID_PROPERTY;
798                 }
799                 dataV.setJson(dataFromDerivedAll);
800                 Either<GraphVertex, TitanOperationStatus> updateDataV = updateOrCopyOnUpdate(dataV, nodeTypeV, label);
801                 if (updateDataV.isRight()) {
802                         return DaoStatusConverter.convertTitanStatusToStorageStatus(updateDataV.right().value());
803                 }
804                 return StorageOperationStatus.OK;
805         }
806
807         @Override
808         public <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) {
809                 fillMetadata(elementV, (NodeType) toscaElementToUpdate);
810         }
811
812 }