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