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