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