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