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