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