[SDC] rebase 1710 code
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / operations / ToscaElementOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.jsontitan.operations;
22
23 import com.google.gson.Gson;
24 import com.google.gson.reflect.TypeToken;
25 import fj.data.Either;
26 import org.apache.tinkerpop.gremlin.structure.Direction;
27 import org.apache.tinkerpop.gremlin.structure.Edge;
28 import org.apache.tinkerpop.gremlin.structure.Vertex;
29 import org.openecomp.sdc.be.config.ConfigurationManager;
30 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
31 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
32 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
33 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
34 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
35 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
36 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
37 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
38 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
39 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
41 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
42 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
43 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
44 import org.openecomp.sdc.be.model.ComponentParametersView;
45 import org.openecomp.sdc.be.model.LifecycleStateEnum;
46 import org.openecomp.sdc.be.model.category.CategoryDefinition;
47 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
48 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
49 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
50 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
51 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
52 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
53 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
54 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
55 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
56 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
57 import org.openecomp.sdc.common.util.ValidationUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.beans.factory.annotation.Autowired;
61
62 import java.lang.reflect.Type;
63 import java.util.*;
64 import java.util.Map.Entry;
65
66 public abstract class ToscaElementOperation extends BaseOperation {
67         private static Logger log = LoggerFactory.getLogger(ToscaElementOperation.class.getName());
68
69         private static final Gson gson = new Gson();
70
71         protected Gson getGson() {
72                 return gson;
73         }
74
75         @Autowired
76         protected CategoryOperation categoryOperation;
77
78         protected Either<GraphVertex, StorageOperationStatus> getComponentByLabelAndId(String uniqueId, ToscaElementTypeEnum nodeType, JsonParseFlagEnum parseFlag) {
79
80                 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<GraphPropertyEnum, Object>();
81                 propertiesToMatch.put(GraphPropertyEnum.UNIQUE_ID, uniqueId);
82
83                 VertexTypeEnum vertexType = ToscaElementTypeEnum.getVertexTypeByToscaType(nodeType);
84                 Either<List<GraphVertex>, TitanOperationStatus> getResponse = titanDao.getByCriteria(vertexType, propertiesToMatch, parseFlag);
85                 if (getResponse.isRight()) {
86                         log.debug("Couldn't fetch component with type {} and unique id {}, error: {}", vertexType, uniqueId, getResponse.right().value());
87                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getResponse.right().value()));
88
89                 }
90                 List<GraphVertex> componentList = getResponse.left().value();
91                 if (componentList.isEmpty()) {
92                         log.debug("Component with type {} and unique id {} was not found", vertexType, uniqueId);
93                         return Either.right(StorageOperationStatus.NOT_FOUND);
94                 }
95                 GraphVertex vertexG = componentList.get(0);
96                 return Either.left(vertexG);
97         }
98
99         public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId) {
100                 return getToscaElement(uniqueId, new ComponentParametersView());
101         }
102
103         public Either<GraphVertex, StorageOperationStatus> markComponentToDelete(GraphVertex componentToDelete) {
104                 Either<GraphVertex, StorageOperationStatus> result = null;
105
106                 Boolean isDeleted = (Boolean) componentToDelete.getMetadataProperty(GraphPropertyEnum.IS_DELETED);
107                 if (isDeleted != null && isDeleted && !(Boolean) componentToDelete.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION)) {
108                         // component already marked for delete
109                         result = Either.left(componentToDelete);
110                         return result;
111                 } else {
112
113                         componentToDelete.addMetadataProperty(GraphPropertyEnum.IS_DELETED, Boolean.TRUE);
114                         componentToDelete.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
115
116                         Either<GraphVertex, TitanOperationStatus> updateNode = titanDao.updateVertex(componentToDelete);
117
118                         StorageOperationStatus updateComponent;
119                         if (updateNode.isRight()) {
120                                 log.debug("Failed to update component {}. status is {}", componentToDelete.getUniqueId(), updateNode.right().value());
121                                 updateComponent = DaoStatusConverter.convertTitanStatusToStorageStatus(updateNode.right().value());
122                                 result = Either.right(updateComponent);
123                                 return result;
124                         }
125
126                         result = Either.left(componentToDelete);
127                         return result;
128                 }
129         }
130
131         /**
132          * Performs a shadow clone of previousToscaElement
133          * 
134          * @param previousToscaElement
135          * @param nextToscaElement
136          * @param user
137          * @return
138          */
139         public Either<GraphVertex, StorageOperationStatus> cloneToscaElement(GraphVertex previousToscaElement, GraphVertex nextToscaElement, GraphVertex user) {
140
141                 Either<GraphVertex, StorageOperationStatus> result = null;
142                 GraphVertex createdToscaElementVertex = null;
143                 TitanOperationStatus status;
144
145                 Either<GraphVertex, TitanOperationStatus> createNextVersionRes = titanDao.createVertex(nextToscaElement);
146                 if (createNextVersionRes.isRight()) {
147                         status = createNextVersionRes.right().value();
148                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create tosca element vertex {} with version {} on graph. Status is {}. ", previousToscaElement.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME),
149                                         previousToscaElement.getMetadataProperty(GraphPropertyEnum.VERSION), status);
150                         result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
151                 }
152                 if (result == null) {
153                         createdToscaElementVertex = createNextVersionRes.left().value();
154                         Map<EdgePropertyEnum, Object> properties = new HashMap<EdgePropertyEnum, Object>();
155                         properties.put(EdgePropertyEnum.STATE, createdToscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE));
156                         status = titanDao.createEdge(user.getVertex(), createdToscaElementVertex.getVertex(), EdgeLabelEnum.STATE, properties);
157                         if (status != TitanOperationStatus.OK) {
158                                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from user vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.STATE, user.getUniqueId(),
159                                                 previousToscaElement.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
160                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
161                         }
162                 }
163                 if (result == null) {
164                         status = titanDao.createEdge(user.getVertex(), createdToscaElementVertex.getVertex(), EdgeLabelEnum.LAST_MODIFIER, new HashMap<>());
165                         if (status != TitanOperationStatus.OK) {
166                                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from user vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.LAST_MODIFIER, user.getUniqueId(),
167                                                 nextToscaElement.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
168                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
169                         }
170                 }
171                 if (result == null) {
172                         status = titanDao.createEdge(user.getVertex(), createdToscaElementVertex.getVertex(), EdgeLabelEnum.CREATOR, new HashMap<>());
173                         if (status != TitanOperationStatus.OK) {
174                                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from user vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.CREATOR, user.getUniqueId(),
175                                                 nextToscaElement.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
176                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
177                         }
178                 }
179                 if (result == null) {
180                         Iterator<Edge> edgesToCopyIter = previousToscaElement.getVertex().edges(Direction.OUT);
181                         while (edgesToCopyIter.hasNext()) {
182                                 Edge currEdge = edgesToCopyIter.next();
183                                 Vertex currVertex = currEdge.inVertex();
184                                 // if(EdgeLabelEnum.getEdgeLabelEnum(currEdge.label()).equals(EdgeLabelEnum.VERSION)){
185                                 // continue;
186                                 // }
187                                 status = titanDao.createEdge(createdToscaElementVertex.getVertex(), currVertex, EdgeLabelEnum.getEdgeLabelEnum(currEdge.label()), currEdge);
188                                 if (status != TitanOperationStatus.OK) {
189                                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from tosca element vertex {} to vertex with label {} on graph. Status is {}. ", currEdge.label(), createdToscaElementVertex.getUniqueId(),
190                                                         currVertex.property(GraphPropertyEnum.LABEL.getProperty()), status);
191                                         result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
192                                         break;
193                                 }
194                         }
195                 }
196
197                 if (result == null) {
198                         result = Either.left(createdToscaElementVertex);
199                 } else {
200                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to clone tosca element {} with the name {}. ", previousToscaElement.getUniqueId(), previousToscaElement.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME));
201                 }
202                 return result;
203         }
204
205         protected TitanOperationStatus setLastModifierFromGraph(GraphVertex componentV, ToscaElement toscaElement) {
206                 Either<GraphVertex, TitanOperationStatus> parentVertex = titanDao.getParentVertex(componentV, EdgeLabelEnum.LAST_MODIFIER, JsonParseFlagEnum.NoParse);
207                 if (parentVertex.isRight()) {
208                         log.debug("Failed to fetch last modifier for tosca element with id {} error {}", componentV.getUniqueId(), parentVertex.right().value());
209                         return parentVertex.right().value();
210                 }
211                 GraphVertex userV = parentVertex.left().value();
212                 String userId = (String) userV.getMetadataProperty(GraphPropertyEnum.USERID);
213                 toscaElement.setLastUpdaterUserId(userId);
214                 toscaElement.setLastUpdaterFullName(buildFullName(userV));
215                 return TitanOperationStatus.OK;
216         }
217
218         public String buildFullName(GraphVertex userV) {
219
220                 String fullName = (String) userV.getMetadataProperty(GraphPropertyEnum.FIRST_NAME);
221                 if (fullName == null) {
222                         fullName = "";
223                 } else {
224                         fullName = fullName + " ";
225                 }
226                 String lastName = (String) userV.getMetadataProperty(GraphPropertyEnum.LAST_NAME);
227                 if (lastName != null) {
228                         fullName += lastName;
229                 }
230                 return fullName;
231         }
232
233         protected TitanOperationStatus setCreatorFromGraph(GraphVertex componentV, ToscaElement toscaElement) {
234                 Either<GraphVertex, TitanOperationStatus> parentVertex = titanDao.getParentVertex(componentV, EdgeLabelEnum.CREATOR, JsonParseFlagEnum.NoParse);
235                 if (parentVertex.isRight()) {
236                         log.debug("Failed to fetch creator for tosca element with id {} error {}", componentV.getUniqueId(), parentVertex.right().value());
237                         return parentVertex.right().value();
238                 }
239                 GraphVertex userV = parentVertex.left().value();
240                 String creatorUserId = (String) userV.getMetadataProperty(GraphPropertyEnum.USERID);
241                 toscaElement.setCreatorUserId(creatorUserId);
242                 toscaElement.setCreatorFullName(buildFullName(userV));
243
244                 return TitanOperationStatus.OK;
245         }
246
247         protected <T extends ToscaElement> T getResourceMetaDataFromResource(T toscaElement) {
248                 if (toscaElement.getNormalizedName() == null || toscaElement.getNormalizedName().isEmpty()) {
249                         toscaElement.setNormalizedName(ValidationUtils.normaliseComponentName(toscaElement.getName()));
250                 }
251                 if (toscaElement.getSystemName() == null || toscaElement.getSystemName().isEmpty()) {
252                         toscaElement.setSystemName(ValidationUtils.convertToSystemName(toscaElement.getName()));
253                 }
254
255                 LifecycleStateEnum lifecycleStateEnum = toscaElement.getLifecycleState();
256                 if (lifecycleStateEnum == null) {
257                         toscaElement.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
258                 }
259                 long currentDate = System.currentTimeMillis();
260                 if (toscaElement.getCreationDate() == null) {
261                         toscaElement.setCreationDate(currentDate);
262                 }
263                 toscaElement.setLastUpdateDate(currentDate);
264
265                 return toscaElement;
266         }
267
268         protected void fillCommonMetadata(GraphVertex nodeTypeVertex, ToscaElement toscaElement) {
269                 if (toscaElement.isHighestVersion() == null) {
270                         toscaElement.setHighestVersion(true);
271                 }
272                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.IS_DELETED, toscaElement.getMetadataValue(JsonPresentationFields.IS_DELETED));
273                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, toscaElement.getMetadataValueOrDefault(JsonPresentationFields.HIGHEST_VERSION, Boolean.TRUE));
274                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.STATE, toscaElement.getMetadataValue(JsonPresentationFields.LIFECYCLE_STATE));
275                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.RESOURCE_TYPE, toscaElement.getMetadataValue(JsonPresentationFields.RESOURCE_TYPE));
276                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.VERSION, toscaElement.getMetadataValue(JsonPresentationFields.VERSION));
277                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME, toscaElement.getMetadataValue(JsonPresentationFields.NORMALIZED_NAME));
278                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, toscaElement.getMetadataValue(JsonPresentationFields.UNIQUE_ID));
279                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
280                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.UUID, toscaElement.getMetadataValue(JsonPresentationFields.UUID));
281                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.IS_ABSTRACT, toscaElement.getMetadataValue(JsonPresentationFields.IS_ABSTRACT));
282                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.INVARIANT_UUID, toscaElement.getMetadataValue(JsonPresentationFields.INVARIANT_UUID));
283                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.NAME, toscaElement.getMetadataValue(JsonPresentationFields.NAME));
284                 nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.SYSTEM_NAME, toscaElement.getMetadataValue(JsonPresentationFields.SYSTEM_NAME));
285                 toscaElement.getMetadata().entrySet().stream().filter(e -> e.getValue() != null).forEach(e -> nodeTypeVertex.setJsonMetadataField(JsonPresentationFields.getByPresentation(e.getKey()), e.getValue()));
286
287                 nodeTypeVertex.setUniqueId(toscaElement.getUniqueId());
288                 nodeTypeVertex.setType(toscaElement.getComponentType());
289
290         }
291
292         protected StorageOperationStatus assosiateToUsers(GraphVertex nodeTypeVertex, ToscaElement toscaElement) {
293                 // handle user
294                 String userId = toscaElement.getCreatorUserId();
295
296                 Either<GraphVertex, TitanOperationStatus> findUser = findUserVertex(userId);
297
298                 if (findUser.isRight()) {
299                         TitanOperationStatus status = findUser.right().value();
300                         log.error("Cannot find user {} in the graph. status is {}", userId, status);
301                         return DaoStatusConverter.convertTitanStatusToStorageStatus(status);
302
303                 }
304                 GraphVertex creatorVertex = findUser.left().value();
305                 GraphVertex updaterVertex = creatorVertex;
306                 String updaterId = toscaElement.getLastUpdaterUserId();
307                 if (updaterId != null && !updaterId.equals(userId)) {
308                         findUser = findUserVertex(updaterId);
309                         if (findUser.isRight()) {
310                                 TitanOperationStatus status = findUser.right().value();
311                                 log.error("Cannot find user {} in the graph. status is {}", userId, status);
312                                 return DaoStatusConverter.convertTitanStatusToStorageStatus(status);
313                         } else {
314                                 updaterVertex = findUser.left().value();
315                         }
316                 }
317                 Map<EdgePropertyEnum, Object> props = new HashMap<EdgePropertyEnum, Object>();
318                 props.put(EdgePropertyEnum.STATE, (String) toscaElement.getMetadataValue(JsonPresentationFields.LIFECYCLE_STATE));
319
320                 TitanOperationStatus result = titanDao.createEdge(updaterVertex, nodeTypeVertex, EdgeLabelEnum.STATE, props);
321                 log.debug("After associating user {} to resource {}. Edge type is {}", updaterVertex, nodeTypeVertex.getUniqueId(), EdgeLabelEnum.STATE);
322                 if (TitanOperationStatus.OK != result) {
323                         return DaoStatusConverter.convertTitanStatusToStorageStatus(result);
324                 }
325                 result = titanDao.createEdge(updaterVertex, nodeTypeVertex, EdgeLabelEnum.LAST_MODIFIER, null);
326                 log.debug("After associating user {}  to resource {}. Edge type is {}", updaterVertex, nodeTypeVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
327                 if (!result.equals(TitanOperationStatus.OK)) {
328                         log.error("Failed to associate user {}  to resource {}. Edge type is {}", updaterVertex, nodeTypeVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
329                         return DaoStatusConverter.convertTitanStatusToStorageStatus(result);
330                 }
331
332                 toscaElement.setLastUpdaterUserId(toscaElement.getCreatorUserId());
333                 toscaElement.setLastUpdaterFullName(toscaElement.getCreatorFullName());
334
335                 result = titanDao.createEdge(creatorVertex, nodeTypeVertex, EdgeLabelEnum.CREATOR, null);
336                 log.debug("After associating user {} to resource {}. Edge type is {} ", creatorVertex, nodeTypeVertex.getUniqueId(), EdgeLabelEnum.CREATOR);
337                 if (!result.equals(TitanOperationStatus.OK)) {
338                         log.error("Failed to associate user {} to resource {}. Edge type is {} ", creatorVertex, nodeTypeVertex.getUniqueId(), EdgeLabelEnum.CREATOR);
339                         return DaoStatusConverter.convertTitanStatusToStorageStatus(result);
340                 }
341                 return StorageOperationStatus.OK;
342         }
343
344         protected StorageOperationStatus assosiateResourceMetadataToCategory(GraphVertex nodeTypeVertex, ToscaElement nodeType) {
345                 String subcategoryName = nodeType.getCategories().get(0).getSubcategories().get(0).getName();
346                 String categoryName = nodeType.getCategories().get(0).getName();
347                 Either<GraphVertex, StorageOperationStatus> getCategoryVertex = getResourceCategoryVertex(nodeType.getUniqueId(), subcategoryName, categoryName);
348
349                 if (getCategoryVertex.isRight()) {
350                         return getCategoryVertex.right().value();
351                 }
352
353                 GraphVertex subCategoryV = getCategoryVertex.left().value();
354
355                 TitanOperationStatus createEdge = titanDao.createEdge(nodeTypeVertex, subCategoryV, EdgeLabelEnum.CATEGORY, new HashMap<>());
356                 if (createEdge != TitanOperationStatus.OK) {
357                         log.trace("Failed to associate resource {} to category {} with id {}", nodeType.getUniqueId(), subcategoryName, subCategoryV.getUniqueId());
358                         return DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge);
359                 }
360                 return StorageOperationStatus.OK;
361         }
362
363         protected Either<GraphVertex, StorageOperationStatus> getResourceCategoryVertex(String elementId, String subcategoryName, String categoryName) {
364                 Either<GraphVertex, StorageOperationStatus> category = categoryOperation.getCategory(categoryName, VertexTypeEnum.RESOURCE_CATEGORY);
365                 if (category.isRight()) {
366                         log.trace("Failed to fetch category {} for resource {} error {}", categoryName, elementId, category.right().value());
367                         return Either.right(category.right().value());
368                 }
369                 GraphVertex categoryV = category.left().value();
370
371                 if (subcategoryName != null) {
372                         Either<GraphVertex, StorageOperationStatus> subCategory = categoryOperation.getSubCategoryForCategory(categoryV, subcategoryName);
373                         if (subCategory.isRight()) {
374                                 log.trace("Failed to fetch subcategory {} of category for resource {} error {}", subcategoryName, categoryName, elementId, subCategory.right().value());
375                                 return Either.right(subCategory.right().value());
376                         }
377
378                         GraphVertex subCategoryV = subCategory.left().value();
379                         return Either.left(subCategoryV);
380                 }
381                 return Either.left(categoryV);
382         }
383
384         private StorageOperationStatus associateArtifactsToResource(GraphVertex nodeTypeVertex, ToscaElement toscaElement) {
385                 Map<String, ArtifactDataDefinition> artifacts = toscaElement.getArtifacts();
386                 Either<GraphVertex, StorageOperationStatus> status;
387                 if (artifacts != null) {
388                         artifacts.values().stream().filter(a -> a.getUniqueId() == null).forEach(a -> {
389                                 String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(nodeTypeVertex.getUniqueId().toLowerCase(), a.getArtifactLabel().toLowerCase());
390                                 a.setUniqueId(uniqueId);
391                         });
392                         status = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ARTIFACTS, EdgeLabelEnum.ARTIFACTS, artifacts);
393                         if (status.isRight()) {
394                                 return status.right().value();
395                         }
396                 }
397                 Map<String, ArtifactDataDefinition> toscaArtifacts = toscaElement.getToscaArtifacts();
398                 if (toscaArtifacts != null) {
399                         toscaArtifacts.values().stream().filter(a -> a.getUniqueId() == null).forEach(a -> {
400                                 String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(nodeTypeVertex.getUniqueId().toLowerCase(), a.getArtifactLabel().toLowerCase());
401                                 a.setUniqueId(uniqueId);
402                         });
403                         status = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.TOSCA_ARTIFACTS, EdgeLabelEnum.TOSCA_ARTIFACTS, toscaArtifacts);
404                         if (status.isRight()) {
405                                 return status.right().value();
406                         }
407                 }
408                 Map<String, ArtifactDataDefinition> deploymentArtifacts = toscaElement.getDeploymentArtifacts();
409                 if (deploymentArtifacts != null) {
410                         deploymentArtifacts.values().stream().filter(a -> a.getUniqueId() == null).forEach(a -> {
411                                 String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(nodeTypeVertex.getUniqueId().toLowerCase(), a.getArtifactLabel().toLowerCase());
412                                 a.setUniqueId(uniqueId);
413                         });
414                         status = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.DEPLOYMENT_ARTIFACTS, EdgeLabelEnum.DEPLOYMENT_ARTIFACTS, deploymentArtifacts);
415                         if (status.isRight()) {
416                                 return status.right().value();
417                         }
418                 }
419                 return StorageOperationStatus.OK;
420         }
421
422         protected TitanOperationStatus disassociateAndDeleteCommonElements(GraphVertex toscaElementVertex) {
423                 TitanOperationStatus status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ARTIFACTS);
424                 if (status != TitanOperationStatus.OK) {
425                         log.debug("Failed to disaccociate artifact for {} error {}", toscaElementVertex.getUniqueId(), status);
426                         return status;
427                 }
428                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.TOSCA_ARTIFACTS);
429                 if (status != TitanOperationStatus.OK) {
430                         log.debug("Failed to disaccociate tosca artifact for {} error {}", toscaElementVertex.getUniqueId(), status);
431                         return status;
432                 }
433                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.DEPLOYMENT_ARTIFACTS);
434                 if (status != TitanOperationStatus.OK) {
435                         log.debug("Failed to deployment artifact for {} error {}", toscaElementVertex.getUniqueId(), status);
436                         return status;
437                 }
438                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.PROPERTIES);
439                 if (status != TitanOperationStatus.OK) {
440                         log.debug("Failed to disaccociate properties for {} error {}", toscaElementVertex.getUniqueId(), status);
441                         return status;
442                 }
443                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ATTRIBUTES);
444                 if (status != TitanOperationStatus.OK) {
445                         log.debug("Failed to disaccociate attributes for {} error {}", toscaElementVertex.getUniqueId(), status);
446                         return status;
447                 }
448                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.ADDITIONAL_INFORMATION);
449                 if (status != TitanOperationStatus.OK) {
450                         log.debug("Failed to disaccociate additional information for {} error {}", toscaElementVertex.getUniqueId(), status);
451                         return status;
452                 }
453                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES);
454                 if (status != TitanOperationStatus.OK) {
455                         log.debug("Failed to disaccociate capabilities for {} error {}", toscaElementVertex.getUniqueId(), status);
456                         return status;
457                 }
458                 status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.REQUIREMENTS);
459                 if (status != TitanOperationStatus.OK) {
460                         log.debug("Failed to disaccociate requirements for {} error {}", toscaElementVertex.getUniqueId(), status);
461                         return status;
462                 }
463                 return TitanOperationStatus.OK;
464         }
465
466         protected StorageOperationStatus assosiateCommonForToscaElement(GraphVertex nodeTypeVertex, ToscaElement toscaElement, List<GraphVertex> derivedResources) {
467
468                 StorageOperationStatus associateUsers = assosiateToUsers(nodeTypeVertex, toscaElement);
469                 if (associateUsers != StorageOperationStatus.OK) {
470                         return associateUsers;
471                 }
472                 StorageOperationStatus associateArtifacts = associateArtifactsToResource(nodeTypeVertex, toscaElement);
473                 if (associateArtifacts != StorageOperationStatus.OK) {
474                         return associateArtifacts;
475                 }
476                 StorageOperationStatus associateProperties = associatePropertiesToResource(nodeTypeVertex, toscaElement, derivedResources);
477                 if (associateProperties != StorageOperationStatus.OK) {
478                         return associateProperties;
479                 }
480                 StorageOperationStatus associateAdditionaInfo = associateAdditionalInfoToResource(nodeTypeVertex, toscaElement);
481                 if (associateAdditionaInfo != StorageOperationStatus.OK) {
482                         return associateAdditionaInfo;
483                 }
484
485                 return StorageOperationStatus.OK;
486         }
487
488         protected StorageOperationStatus associatePropertiesToResource(GraphVertex nodeTypeVertex, ToscaElement nodeType, List<GraphVertex> derivedResources) {
489                 // Note : currently only one derived supported!!!!
490                 Either<Map<String, PropertyDataDefinition>, StorageOperationStatus> dataFromDerived = getDataFromDerived(derivedResources, EdgeLabelEnum.PROPERTIES);
491                 if (dataFromDerived.isRight()) {
492                         return dataFromDerived.right().value();
493                 }
494                 Map<String, PropertyDataDefinition> propertiesAll = dataFromDerived.left().value();
495
496                 Map<String, PropertyDataDefinition> properties = nodeType.getProperties();
497
498                 if (properties != null) {
499                         properties.values().stream().filter(p -> p.getUniqueId() == null).forEach(p -> {
500                                 String uid = UniqueIdBuilder.buildPropertyUniqueId(nodeTypeVertex.getUniqueId(), p.getName());
501                                 p.setUniqueId(uid);
502                         });
503
504                         Either<Map<String, PropertyDataDefinition>, String> eitherMerged = ToscaDataDefinition.mergeDataMaps(propertiesAll, properties);
505                         if (eitherMerged.isRight()) {
506                                 // TODO re-factor error handling - moving BL to operation resulted in loss of info about the invalid property
507                                 log.debug("property {} cannot be overriden", eitherMerged.right().value());
508                                 return StorageOperationStatus.INVALID_PROPERTY;
509                         }
510                 }
511                 if (!propertiesAll.isEmpty()) {
512                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.PROPERTIES, EdgeLabelEnum.PROPERTIES, propertiesAll);
513                         if (assosiateElementToData.isRight()) {
514                                 return assosiateElementToData.right().value();
515                         }
516                 }
517                 return StorageOperationStatus.OK;
518         }
519
520         private StorageOperationStatus associateAdditionalInfoToResource(GraphVertex nodeTypeVertex, ToscaElement nodeType) {
521                 Map<String, AdditionalInfoParameterDataDefinition> additionalInformation = nodeType.getAdditionalInformation();
522                 if (additionalInformation != null) {
523                         Either<GraphVertex, StorageOperationStatus> assosiateElementToData = assosiateElementToData(nodeTypeVertex, VertexTypeEnum.ADDITIONAL_INFORMATION, EdgeLabelEnum.ADDITIONAL_INFORMATION, additionalInformation);
524                         if (assosiateElementToData.isRight()) {
525                                 return assosiateElementToData.right().value();
526                         }
527                 }
528                 return StorageOperationStatus.OK;
529         }
530
531         protected <T extends ToscaDataDefinition> Either<Map<String, T>, StorageOperationStatus> getDataFromDerived(List<GraphVertex> derivedResources, EdgeLabelEnum edge) {
532                 Map<String, T> propertiesAll = new HashMap<>();
533
534                 if (derivedResources != null && !derivedResources.isEmpty()) {
535                         for (GraphVertex derived : derivedResources) {
536                                 Either<List<GraphVertex>, TitanOperationStatus> derivedProperties = titanDao.getChildrenVertecies(derived, edge, JsonParseFlagEnum.ParseJson);
537                                 if (derivedProperties.isRight()) {
538                                         if (derivedProperties.right().value() != TitanOperationStatus.NOT_FOUND) {
539                                                 log.debug("Failed to get properties for derived from {} error {}", derived.getUniqueId(), derivedProperties.right().value());
540                                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(derivedProperties.right().value()));
541                                         } else {
542                                                 continue;
543                                         }
544                                 }
545                                 List<GraphVertex> propList = derivedProperties.left().value();
546                                 for (GraphVertex propV : propList) {
547                                         Map<String, T> propertiesFromDerived = (Map<String, T>) propV.getJson();
548                                         if (propertiesFromDerived != null) {
549                                                 propertiesFromDerived.entrySet().forEach(x -> x.getValue().setOwnerIdIfEmpty(derived.getUniqueId()));
550                                                 propertiesAll.putAll(propertiesFromDerived);
551                                         }
552                                 }
553                         }
554                 }
555                 return Either.left(propertiesAll);
556         }
557
558         protected TitanOperationStatus setArtifactsFromGraph(GraphVertex componentV, ToscaElement toscaElement) {
559                 Either<Map<String, ArtifactDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ARTIFACTS);
560                 if (result.isLeft()) {
561                         toscaElement.setArtifacts(result.left().value());
562                 } else {
563                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
564                                 return result.right().value();
565                         }
566                 }
567                 result = getDataFromGraph(componentV, EdgeLabelEnum.DEPLOYMENT_ARTIFACTS);
568                 if (result.isLeft()) {
569                         toscaElement.setDeploymentArtifacts(result.left().value());
570                 } else {
571                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
572                                 return result.right().value();
573                         }
574                 }
575                 result = getDataFromGraph(componentV, EdgeLabelEnum.TOSCA_ARTIFACTS);
576                 if (result.isLeft()) {
577                         toscaElement.setToscaArtifacts(result.left().value());
578                 } else {
579                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
580                                 return result.right().value();
581                         }
582                 }
583                 return TitanOperationStatus.OK;
584         }
585
586         protected TitanOperationStatus setAllVersions(GraphVertex componentV, ToscaElement toscaElement) {
587                 Map<String, String> allVersion = new HashMap<>();
588
589                 allVersion.put((String) componentV.getMetadataProperty(GraphPropertyEnum.VERSION), componentV.getUniqueId());
590                 ArrayList<GraphVertex> allChildrenAndParants = new ArrayList<GraphVertex>();
591                 Either<GraphVertex, TitanOperationStatus> childResourceRes = titanDao.getChildVertex(componentV, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
592                 while (childResourceRes.isLeft()) {
593                         GraphVertex child = childResourceRes.left().value();
594                         allChildrenAndParants.add(child);
595                         childResourceRes = titanDao.getChildVertex(child, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
596                 }
597                 TitanOperationStatus operationStatus = childResourceRes.right().value();
598
599                 if (operationStatus != TitanOperationStatus.NOT_FOUND) {
600                         return operationStatus;
601                 } else {
602                         Either<GraphVertex, TitanOperationStatus> parentResourceRes = titanDao.getParentVertex(componentV, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
603                         while (parentResourceRes.isLeft()) {
604                                 GraphVertex parent = parentResourceRes.left().value();
605                                 allChildrenAndParants.add(parent);
606                                 parentResourceRes = titanDao.getParentVertex(parent, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
607                         }
608                         operationStatus = parentResourceRes.right().value();
609                         if (operationStatus != TitanOperationStatus.NOT_FOUND) {
610                                 return operationStatus;
611                         } else {
612                                 allChildrenAndParants.stream().filter(vertex -> {
613                                         Boolean isDeleted = (Boolean) vertex.getMetadataProperty(GraphPropertyEnum.IS_DELETED);
614                                         return (isDeleted == null || isDeleted == false);
615                                 }).forEach(vertex -> allVersion.put((String) vertex.getMetadataProperty(GraphPropertyEnum.VERSION), vertex.getUniqueId()));
616
617                                 toscaElement.setAllVersions(allVersion);
618                                 return TitanOperationStatus.OK;
619                         }
620                 }
621         }
622
623         protected <T extends ToscaElement> Either<List<T>, StorageOperationStatus> getFollowedComponent(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates, ComponentTypeEnum neededType) {
624
625                 Either<List<T>, StorageOperationStatus> result = null;
626
627                 Map<GraphPropertyEnum, Object> props = null;
628
629                 if (userId != null) {
630                         props = new HashMap<>();
631                         // for Designer retrieve specific user
632                         props.put(GraphPropertyEnum.USERID, userId);
633                 }
634                 // in case of user id == null -> get all users by label
635                 // for Tester and Admin retrieve all users
636                 Either<List<GraphVertex>, TitanOperationStatus> usersByCriteria = titanDao.getByCriteria(VertexTypeEnum.USER, props, JsonParseFlagEnum.NoParse);
637                 if (usersByCriteria.isRight()) {
638                         log.debug("Failed to fetch users by criteria {} error {}", props, usersByCriteria.right().value());
639                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(usersByCriteria.right().value()));
640                 }
641                 List<GraphVertex> users = usersByCriteria.left().value();
642
643                 List<T> components = new ArrayList<>();
644                 List<T> componentsPerUser;
645                 for (GraphVertex userV : users) {
646
647                         HashSet<String> ids = new HashSet<String>();
648                         Either<List<GraphVertex>, TitanOperationStatus> childrenVertecies = titanDao.getChildrenVertecies(userV, EdgeLabelEnum.STATE, JsonParseFlagEnum.NoParse);
649                         if (childrenVertecies.isRight() && childrenVertecies.right().value() != TitanOperationStatus.NOT_FOUND) {
650                                 log.debug("Failed to fetch children vertices for user {} by edge {} error {}", userV.getMetadataProperty(GraphPropertyEnum.USERID), EdgeLabelEnum.STATE, childrenVertecies.right().value());
651                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenVertecies.right().value()));
652                         }
653
654                         // get all resource with current state
655                         if (childrenVertecies.isLeft()) {
656                                 componentsPerUser = fetchComponents(lifecycleStates, childrenVertecies.left().value(), neededType, EdgeLabelEnum.STATE);
657
658                                 if (componentsPerUser != null) {
659                                         for (T comp : componentsPerUser) {
660                                                 ids.add(comp.getUniqueId());
661                                                 components.add(comp);
662                                         }
663                                 }
664                         }
665                         if (lastStateStates != null && !lastStateStates.isEmpty()) {
666                                 // get all resource with last state
667                                 childrenVertecies = titanDao.getChildrenVertecies(userV, EdgeLabelEnum.LAST_STATE, JsonParseFlagEnum.NoParse);
668                                 if (childrenVertecies.isRight() && childrenVertecies.right().value() != TitanOperationStatus.NOT_FOUND) {
669                                         log.debug("Failed to fetch children vertices for user {} by edge {} error {}", userV.getMetadataProperty(GraphPropertyEnum.USERID), EdgeLabelEnum.LAST_STATE, childrenVertecies.right().value());
670                                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenVertecies.right().value()));
671                                 }
672                                 if (childrenVertecies.isLeft()) {
673                                         boolean isFirst;
674                                         componentsPerUser = fetchComponents(lastStateStates, childrenVertecies.left().value(), neededType, EdgeLabelEnum.LAST_STATE);
675                                         if (componentsPerUser != null) {
676                                                 for (T comp : componentsPerUser) {
677                                                         isFirst = true;
678
679                                                         if (ids.contains(comp.getUniqueId())) {
680                                                                 isFirst = false;
681                                                         }
682                                                         if (isFirst == true) {
683                                                                 components.add(comp);
684                                                         }
685
686                                                 }
687                                         }
688                                 }
689                         }
690
691                 } // whlile users
692                 ;
693                 result = Either.left(components);
694                 return result;
695
696         }
697
698         private <T extends ToscaElement> List<T> fetchComponents(Set<LifecycleStateEnum> lifecycleStates, List<GraphVertex> vertices, ComponentTypeEnum neededType, EdgeLabelEnum edgelabel) {
699                 List<T> components = new ArrayList<>();
700                 for (GraphVertex node : vertices) {
701
702                         Iterator<Edge> edges = node.getVertex().edges(Direction.IN, edgelabel.name());
703                         while (edges.hasNext()) {
704                                 Edge edge = edges.next();
705                                 String stateStr = (String) titanDao.getProperty(edge, EdgePropertyEnum.STATE);
706
707                                 LifecycleStateEnum nodeState = LifecycleStateEnum.findState(stateStr);
708                                 if (nodeState == null) {
709                                         log.debug("no supported STATE {} for element  {}", stateStr, node.getUniqueId());
710                                         continue;
711                                 }
712                                 if (lifecycleStates != null && lifecycleStates.contains(nodeState)) {
713
714                                         Boolean isDeleted = (Boolean) node.getMetadataProperty(GraphPropertyEnum.IS_DELETED);
715                                         if (isDeleted != null && isDeleted) {
716                                                 log.trace("Deleted element  {}, discard", node.getUniqueId());
717                                                 continue;
718                                         }
719
720                                         Boolean isHighest = (Boolean) node.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
721                                         if (isHighest) {
722
723                                                 ComponentTypeEnum componentType = node.getType();
724                                                 // get only latest versions
725
726                                                 if (componentType == null) {
727                                                         log.debug("No supported type {} for vertex {}", componentType, node.getUniqueId());
728                                                         continue;
729                                                 }
730                                                 if (neededType == componentType) {
731                                                         switch (componentType) {
732                                                         case SERVICE:
733                                                         case PRODUCT:
734                                                                 handleNode(components, node, componentType);
735                                                                 break;
736                                                         case RESOURCE:
737                                                                 Boolean isAbtract = (Boolean) node.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
738                                                                 if (isAbtract == null || false == isAbtract) {
739                                                                         handleNode(components, node, componentType);
740                                                                 } // if not abstract
741                                                                 break;
742                                                         default:
743                                                                 log.debug("not supported node type {}", componentType);
744                                                                 break;
745                                                         }// case
746                                                 } // needed type
747                                         }
748                                 } // if
749                         } // while edges
750                 } // while resources
751                 return components;
752         }
753
754         protected <T extends ToscaElement> void handleNode(List<T> components, GraphVertex vertexComponent, ComponentTypeEnum nodeType) {
755
756                 Either<T, StorageOperationStatus> component = getLightComponent(vertexComponent, nodeType, new ComponentParametersView(true));
757                 if (component.isRight()) {
758                         log.debug("Failed to get component for id =  {}  error : {} skip resource", vertexComponent.getUniqueId(), component.right().value());
759                 } else {
760                         components.add(component.left().value());
761                 }
762         }
763
764         protected <T extends ToscaElement> Either<T, StorageOperationStatus> getLightComponent(String componentUid, ComponentTypeEnum nodeType, ComponentParametersView parametersFilter) {
765                 Either<GraphVertex, TitanOperationStatus> getVertexRes = titanDao.getVertexById(componentUid);
766                 if (getVertexRes.isRight()) {
767                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexRes.right().value()));
768                 }
769                 return getLightComponent(getVertexRes.left().value(), nodeType, parametersFilter);
770         }
771
772         protected <T extends ToscaElement> Either<T, StorageOperationStatus> getLightComponent(GraphVertex vertexComponent, ComponentTypeEnum nodeType, ComponentParametersView parametersFilter) {
773
774                 log.trace("Starting to build light component of type {}, id {}", nodeType, vertexComponent.getUniqueId());
775
776                 titanDao.parseVertexProperties(vertexComponent, JsonParseFlagEnum.ParseMetadata);
777
778                 T toscaElement = convertToComponent(vertexComponent);
779
780                 TitanOperationStatus status = setCreatorFromGraph(vertexComponent, toscaElement);
781                 if (status != TitanOperationStatus.OK) {
782                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
783                 }
784
785                 status = setLastModifierFromGraph(vertexComponent, toscaElement);
786                 if (status != TitanOperationStatus.OK) {
787                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
788                 }
789                 status = setCategoriesFromGraph(vertexComponent, toscaElement);
790                 if (status != TitanOperationStatus.OK) {
791                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
792                 }
793                 if (!parametersFilter.isIgnoreAllVersions()) {
794                         status = setAllVersions(vertexComponent, toscaElement);
795                         if (status != TitanOperationStatus.OK) {
796                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
797                         }
798                 }
799                 if (!parametersFilter.isIgnoreCapabilities()) {
800                         status = setCapabilitiesFromGraph(vertexComponent, toscaElement);
801                         if (status != TitanOperationStatus.OK) {
802                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
803                         }
804                 }
805                 if (!parametersFilter.isIgnoreRequirements()) {
806                         status = setRequirementsFromGraph(vertexComponent, toscaElement);
807                         if (status != TitanOperationStatus.OK) {
808                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
809                         }
810                 }
811                 log.debug("Ended to build light component of type {}, id {}", nodeType, vertexComponent.getUniqueId());
812                 return Either.left(toscaElement);
813         }
814
815         @SuppressWarnings("unchecked")
816         protected <T extends ToscaElement> T convertToComponent(GraphVertex componentV) {
817                 ToscaElement toscaElement = null;
818                 VertexTypeEnum label = componentV.getLabel();
819                 switch (label) {
820                 case NODE_TYPE:
821                         toscaElement = new NodeType();
822                         break;
823                 case TOPOLOGY_TEMPLATE:
824                         toscaElement = new TopologyTemplate();
825                         break;
826                 default:
827                         log.debug("Not supported tosca type {}", label);
828                         break;
829                 }
830
831                 Map<String, Object> jsonMetada = componentV.getMetadataJson();
832                 if (toscaElement != null) {
833                         toscaElement.setMetadata(jsonMetada);
834                 }
835                 return (T) toscaElement;
836         }
837
838         protected TitanOperationStatus setResourceCategoryFromGraph(GraphVertex componentV, ToscaElement toscaElement) {
839                 List<CategoryDefinition> categories = new ArrayList<>();
840                 SubCategoryDefinition subcategory;
841
842                 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(componentV, EdgeLabelEnum.CATEGORY, JsonParseFlagEnum.NoParse);
843                 if (childVertex.isRight()) {
844                         log.debug("failed to fetch {} for tosca element with id {}, error {}", EdgeLabelEnum.CATEGORY, componentV.getUniqueId(), childVertex.right().value());
845                         return childVertex.right().value();
846                 }
847                 GraphVertex subCategoryV = childVertex.left().value();
848                 Map<GraphPropertyEnum, Object> metadataProperties = subCategoryV.getMetadataProperties();
849                 subcategory = new SubCategoryDefinition();
850                 subcategory.setUniqueId(subCategoryV.getUniqueId());
851                 subcategory.setNormalizedName((String) metadataProperties.get(GraphPropertyEnum.NORMALIZED_NAME));
852                 subcategory.setName((String) metadataProperties.get(GraphPropertyEnum.NAME));
853
854                 Type listTypeSubcat = new TypeToken<List<String>>() {
855                 }.getType();
856                 List<String> iconsfromJsonSubcat = getGson().fromJson((String) metadataProperties.get(GraphPropertyEnum.ICONS), listTypeSubcat);
857                 subcategory.setIcons(iconsfromJsonSubcat);
858
859                 Either<GraphVertex, TitanOperationStatus> parentVertex = titanDao.getParentVertex(subCategoryV, EdgeLabelEnum.SUB_CATEGORY, JsonParseFlagEnum.NoParse);
860                 if (parentVertex.isRight()) {
861                         log.debug("failed to fetch {} for category with id {}, error {}", EdgeLabelEnum.SUB_CATEGORY, subCategoryV.getUniqueId(), parentVertex.right().value());
862                         return childVertex.right().value();
863                 }
864                 GraphVertex categoryV = parentVertex.left().value();
865                 metadataProperties = categoryV.getMetadataProperties();
866
867                 CategoryDefinition category = new CategoryDefinition();
868                 category.setUniqueId(categoryV.getUniqueId());
869                 category.setNormalizedName((String) metadataProperties.get(GraphPropertyEnum.NORMALIZED_NAME));
870                 category.setName((String) metadataProperties.get(GraphPropertyEnum.NAME));
871
872                 Type listTypeCat = new TypeToken<List<String>>() {
873                 }.getType();
874                 List<String> iconsfromJsonCat = getGson().fromJson((String) metadataProperties.get(GraphPropertyEnum.ICONS), listTypeCat);
875                 category.setIcons(iconsfromJsonCat);
876
877                 category.addSubCategory(subcategory);
878                 categories.add(category);
879                 toscaElement.setCategories(categories);
880
881                 return TitanOperationStatus.OK;
882         }
883
884         public <T extends ToscaElement> Either<T, StorageOperationStatus> updateToscaElement(T toscaElementToUpdate, GraphVertex elementV, ComponentParametersView filterResult) {
885                 Either<T, StorageOperationStatus> result = null;
886
887                 log.debug("In updateToscaElement. received component uid = {}", (toscaElementToUpdate == null ? null : toscaElementToUpdate.getUniqueId()));
888                 if (toscaElementToUpdate == null) {
889                         log.error("Service object is null");
890                         result = Either.right(StorageOperationStatus.BAD_REQUEST);
891                         return result;
892                 }
893
894                 String modifierUserId = toscaElementToUpdate.getLastUpdaterUserId();
895                 if (modifierUserId == null || modifierUserId.isEmpty()) {
896                         log.error("UserId is missing in the request.");
897                         result = Either.right(StorageOperationStatus.BAD_REQUEST);
898                         return result;
899                 }
900                 Either<GraphVertex, TitanOperationStatus> findUser = findUserVertex(modifierUserId);
901
902                 if (findUser.isRight()) {
903                         TitanOperationStatus status = findUser.right().value();
904                         log.error("Cannot find user {} in the graph. status is {}", modifierUserId, status);
905                         return result;
906                 }
907
908                 GraphVertex modifierV = findUser.left().value();
909                 // UserData modifierUserData = findUser.left().value();
910                 String toscaElementId = toscaElementToUpdate.getUniqueId();
911
912                 Either<GraphVertex, TitanOperationStatus> parentVertex = titanDao.getParentVertex(elementV, EdgeLabelEnum.LAST_MODIFIER, JsonParseFlagEnum.NoParse);
913                 if (parentVertex.isRight()) {
914                         log.debug("Failed to fetch last modifier for tosca element with id {} error {}", toscaElementId, parentVertex.right().value());
915                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(parentVertex.right().value()));
916                 }
917                 GraphVertex userV = parentVertex.left().value();
918                 String currentModifier = (String) userV.getMetadataProperty(GraphPropertyEnum.USERID);
919
920                 String prevSystemName = (String) elementV.getMetadataProperty(GraphPropertyEnum.SYSTEM_NAME);
921
922                 if (currentModifier.equals(modifierUserId)) {
923                         log.debug("Graph LAST MODIFIER edge should not be changed since the modifier is the same as the last modifier.");
924                 } else {
925                         log.debug("Going to update the last modifier user of the resource from {} to {}", currentModifier, modifierUserId);
926                         StorageOperationStatus status = moveLastModifierEdge(elementV, modifierV);
927                         log.debug("Finish to update the last modifier user of the resource from {} to {}. status is {}", currentModifier, modifierUserId, status);
928                         if (status != StorageOperationStatus.OK) {
929                                 result = Either.right(status);
930                                 return result;
931                         }
932                 }
933
934                 final long currentTimeMillis = System.currentTimeMillis();
935                 log.debug("Going to update the last Update Date of the resource from {} to {}", elementV.getJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE), currentTimeMillis);
936                 elementV.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, currentTimeMillis);
937
938                 StorageOperationStatus checkCategories = validateCategories(toscaElementToUpdate, elementV);
939                 if (checkCategories != StorageOperationStatus.OK) {
940                         result = Either.right(checkCategories);
941                         return result;
942                 }
943
944                 // update all data on vertex
945                 fillToscaElementVertexData(elementV, toscaElementToUpdate, JsonParseFlagEnum.ParseMetadata);
946
947                 Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(elementV);
948
949                 if (updateElement.isRight()) {
950                         log.error("Failed to update resource {}. status is {}", toscaElementId, updateElement.right().value());
951                         result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()));
952                         return result;
953                 }
954                 GraphVertex updateElementV = updateElement.left().value();
955
956                 // DE230195 in case resource name changed update TOSCA artifacts
957                 // file names accordingly
958                 String newSystemName = (String) updateElementV.getMetadataProperty(GraphPropertyEnum.SYSTEM_NAME);
959                 if (newSystemName != null && !newSystemName.equals(prevSystemName)) {
960                         Either<Map<String, ArtifactDataDefinition>, TitanOperationStatus> resultToscaArt = getDataFromGraph(updateElementV, EdgeLabelEnum.TOSCA_ARTIFACTS);
961                         if (resultToscaArt.isRight()) {
962                                 log.debug("Failed to get  tosca artifact from graph for tosca element {} error {}", toscaElementId, resultToscaArt.right().value());
963                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resultToscaArt.right().value()));
964                         }
965
966                         Map<String, ArtifactDataDefinition> toscaArtifacts = resultToscaArt.left().value();
967                         if (toscaArtifacts != null) {
968                                 for (Entry<String, ArtifactDataDefinition> artifact : toscaArtifacts.entrySet()) {
969                                         generateNewToscaFileName(toscaElementToUpdate.getComponentType().getValue().toLowerCase(), newSystemName, artifact.getValue());
970                                 }
971                                 // TODO call to new Artifact operation in order to update list of artifacts
972
973                         }
974                         // US833308 VLI in service - specific network_role property value logic
975                         if (ComponentTypeEnum.SERVICE == toscaElementToUpdate.getComponentType()) {
976                                 // update method logs success/error and returns boolean (true if nothing fails)
977                                 // TODO!!!!
978                                 // updateServiceNameInVLIsNetworkRolePropertyValues(component, prevSystemName, newSystemName);
979                         }
980                 }
981
982                 if (toscaElementToUpdate.getComponentType() == ComponentTypeEnum.RESOURCE) {
983                         StorageOperationStatus resultDerived = updateDerived(toscaElementToUpdate, updateElementV);
984                         if (resultDerived != StorageOperationStatus.OK) {
985                                 log.debug("Failed to update from derived data for element {} error {}", toscaElementId, resultDerived);
986                                 return Either.right(resultDerived);
987                         }
988                 }
989
990                 Either<T, StorageOperationStatus> updatedResource = getToscaElement(updateElementV, filterResult);
991                 if (updatedResource.isRight()) {
992                         log.error("Failed to fetch tosca element {} after update , error {}", toscaElementId, updatedResource.right().value());
993                         result = Either.right(StorageOperationStatus.BAD_REQUEST);
994                         return result;
995                 }
996
997                 T updatedResourceValue = updatedResource.left().value();
998                 result = Either.left(updatedResourceValue);
999
1000                 return result;
1001         }
1002
1003         protected StorageOperationStatus moveLastModifierEdge(GraphVertex elementV, GraphVertex modifierV) {
1004                 return DaoStatusConverter.convertTitanStatusToStorageStatus(titanDao.moveEdge(elementV, modifierV, EdgeLabelEnum.LAST_MODIFIER, Direction.IN));
1005         }
1006
1007         protected StorageOperationStatus moveCategoryEdge(GraphVertex elementV, GraphVertex categoryV) {
1008                 return DaoStatusConverter.convertTitanStatusToStorageStatus(titanDao.moveEdge(elementV, categoryV, EdgeLabelEnum.CATEGORY, Direction.OUT));
1009         }
1010
1011         private void generateNewToscaFileName(String componentType, String componentName, ArtifactDataDefinition artifactInfo) {
1012                 Map<String, Object> getConfig = (Map<String, Object>) ConfigurationManager.getConfigurationManager().getConfiguration().getToscaArtifacts().entrySet().stream().filter(p -> p.getKey().equalsIgnoreCase(artifactInfo.getArtifactLabel()))
1013                                 .findAny().get().getValue();
1014                 artifactInfo.setArtifactName(componentType + "-" + componentName + getConfig.get("artifactName"));
1015         }
1016
1017         protected <T extends ToscaElement> StorageOperationStatus validateResourceCategory(T toscaElementToUpdate, GraphVertex elementV) {
1018                 StorageOperationStatus status = StorageOperationStatus.OK;
1019                 List<CategoryDefinition> newCategoryList = toscaElementToUpdate.getCategories();
1020                 CategoryDefinition newCategory = newCategoryList.get(0);
1021
1022                 Either<GraphVertex, TitanOperationStatus> childVertex = titanDao.getChildVertex(elementV, EdgeLabelEnum.CATEGORY, JsonParseFlagEnum.NoParse);
1023                 if (childVertex.isRight()) {
1024                         log.debug("failed to fetch {} for tosca element with id {}, error {}", EdgeLabelEnum.CATEGORY, elementV.getUniqueId(), childVertex.right().value());
1025                         return DaoStatusConverter.convertTitanStatusToStorageStatus(childVertex.right().value());
1026                 }
1027                 GraphVertex subCategoryV = childVertex.left().value();
1028                 Map<GraphPropertyEnum, Object> metadataProperties = subCategoryV.getMetadataProperties();
1029                 String subCategoryNameCurrent = (String) metadataProperties.get(GraphPropertyEnum.NAME);
1030
1031                 Either<GraphVertex, TitanOperationStatus> parentVertex = titanDao.getParentVertex(subCategoryV, EdgeLabelEnum.SUB_CATEGORY, JsonParseFlagEnum.NoParse);
1032                 if (parentVertex.isRight()) {
1033                         log.debug("failed to fetch {} for category with id {}, error {}", EdgeLabelEnum.SUB_CATEGORY, subCategoryV.getUniqueId(), parentVertex.right().value());
1034                         return DaoStatusConverter.convertTitanStatusToStorageStatus(childVertex.right().value());
1035                 }
1036                 GraphVertex categoryV = parentVertex.left().value();
1037                 metadataProperties = categoryV.getMetadataProperties();
1038                 String categoryNameCurrent = (String) metadataProperties.get(GraphPropertyEnum.NAME);
1039
1040                 boolean categoryWasChanged = false;
1041
1042                 String newCategoryName = newCategory.getName();
1043                 SubCategoryDefinition newSubcategory = newCategory.getSubcategories().get(0);
1044                 String newSubCategoryName = newSubcategory.getName();
1045                 if (newCategoryName != null && false == newCategoryName.equals(categoryNameCurrent)) {
1046                         // the category was changed
1047                         categoryWasChanged = true;
1048                 } else {
1049                         // the sub-category was changed
1050                         if (newSubCategoryName != null && false == newSubCategoryName.equals(subCategoryNameCurrent)) {
1051                                 log.debug("Going to update the category of the resource from {} to {}", categoryNameCurrent, newCategory);
1052                                 categoryWasChanged = true;
1053                         }
1054                 }
1055                 if (categoryWasChanged) {
1056                         Either<GraphVertex, StorageOperationStatus> getCategoryVertex = getResourceCategoryVertex(elementV.getUniqueId(), newSubCategoryName, newCategoryName);
1057
1058                         if (getCategoryVertex.isRight()) {
1059                                 return getCategoryVertex.right().value();
1060                         }
1061                         GraphVertex newCategoryV = getCategoryVertex.left().value();
1062                         status = moveCategoryEdge(elementV, newCategoryV);
1063                         log.debug("Going to update the category of the resource from {} to {}. status is {}", categoryNameCurrent, newCategory, status);
1064                 }
1065                 return status;
1066         }
1067
1068         public <T extends ToscaElement> Either<List<T>, StorageOperationStatus> getElementCatalogData(ComponentTypeEnum componentType, List<ResourceTypeEnum> excludeTypes, boolean isHighestVersions) {
1069                 Either<List<GraphVertex>, TitanOperationStatus> listOfComponents;
1070                 if (isHighestVersions) {
1071                         listOfComponents = getListOfHighestComponents(componentType, excludeTypes);
1072                 }
1073                 else {
1074                         listOfComponents = getListOfHighestAndAllCertifiedComponents(componentType, excludeTypes);
1075                 }
1076
1077                 if (listOfComponents.isRight() && listOfComponents.right().value() != TitanOperationStatus.NOT_FOUND) {
1078                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(listOfComponents.right().value()));
1079                 }
1080                 List<T> result = new ArrayList<>();
1081                 if (listOfComponents.isLeft()) {
1082                         List<GraphVertex> highestAndAllCertified = listOfComponents.left().value();
1083                         if (highestAndAllCertified != null && false == highestAndAllCertified.isEmpty()) {
1084                                 for (GraphVertex vertexComponent : highestAndAllCertified) {
1085                                         Either<T, StorageOperationStatus> component = getLightComponent(vertexComponent, componentType, new ComponentParametersView(true));
1086                                         if (component.isRight()) {
1087                                                 log.debug("Failed to fetch light element for {} error {}", vertexComponent.getUniqueId(), component.right().value());
1088                                                 return Either.right(component.right().value());
1089                                         } else {
1090                                                 result.add(component.left().value());
1091                                         }
1092                                 }
1093                         }
1094                 }
1095                 return Either.left(result);
1096         }
1097
1098         private Either<List<GraphVertex>, TitanOperationStatus> getListOfHighestComponents(ComponentTypeEnum componentType, List<ResourceTypeEnum> excludeTypes) {
1099                 Map<GraphPropertyEnum, Object> propertiesToMatch = new HashMap<>();
1100                 Map<GraphPropertyEnum, Object> propertiesHasNotToMatch = new HashMap<>();
1101                 propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name());
1102                 propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
1103
1104                 if (componentType == ComponentTypeEnum.RESOURCE) {
1105                         propertiesToMatch.put(GraphPropertyEnum.IS_ABSTRACT, false);
1106                         propertiesHasNotToMatch.put(GraphPropertyEnum.RESOURCE_TYPE, excludeTypes);
1107                 }
1108                 propertiesHasNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
1109
1110                 return titanDao.getByCriteria(null, propertiesToMatch, propertiesHasNotToMatch, JsonParseFlagEnum.ParseMetadata);
1111         }
1112
1113         // highest + (certified && !highest)
1114         public Either<List<GraphVertex>, TitanOperationStatus> getListOfHighestAndAllCertifiedComponents(ComponentTypeEnum componentType, List<ResourceTypeEnum> excludeTypes) {
1115                 long startFetchAllStates = System.currentTimeMillis();
1116                 Either<List<GraphVertex>, TitanOperationStatus> highestNodes = getListOfHighestComponents(componentType, excludeTypes);
1117
1118                 Map<GraphPropertyEnum, Object> propertiesToMatchCertified = new HashMap<>();
1119                 Map<GraphPropertyEnum, Object> propertiesHasNotToMatchCertified = new HashMap<>();
1120                 propertiesToMatchCertified.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1121                 propertiesToMatchCertified.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name());
1122                 if (componentType == ComponentTypeEnum.RESOURCE) {
1123                         propertiesToMatchCertified.put(GraphPropertyEnum.IS_ABSTRACT, false);
1124                         propertiesHasNotToMatchCertified.put(GraphPropertyEnum.RESOURCE_TYPE, excludeTypes);
1125                 }
1126
1127                 propertiesHasNotToMatchCertified.put(GraphPropertyEnum.IS_DELETED, true);
1128                 propertiesHasNotToMatchCertified.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
1129
1130                 Either<List<GraphVertex>, TitanOperationStatus> certifiedNotHighestNodes = titanDao.getByCriteria(null, propertiesToMatchCertified, propertiesHasNotToMatchCertified,
1131                                 JsonParseFlagEnum.ParseMetadata);
1132                 if (certifiedNotHighestNodes.isRight() && certifiedNotHighestNodes.right().value() != TitanOperationStatus.NOT_FOUND) {
1133                         return Either.right(certifiedNotHighestNodes.right().value());
1134                 }
1135
1136                 long endFetchAllStates = System.currentTimeMillis();
1137
1138                 List<GraphVertex> allNodes = new ArrayList<>();
1139
1140                 if (certifiedNotHighestNodes.isLeft()) {
1141                         allNodes.addAll(certifiedNotHighestNodes.left().value());
1142                 }
1143                 if (highestNodes.isLeft()) {
1144                         allNodes.addAll(highestNodes.left().value());
1145                 }
1146
1147                 log.debug("Fetch catalog {}s all states from graph took {} ms", componentType, endFetchAllStates - startFetchAllStates);
1148                 return Either.left(allNodes);
1149         }
1150
1151         protected Either<List<GraphVertex>, StorageOperationStatus> getAllComponentsMarkedForDeletion(ComponentTypeEnum componentType) {
1152
1153                 // get all components marked for delete
1154                 Map<GraphPropertyEnum, Object> props = new HashMap<GraphPropertyEnum, Object>();
1155                 props.put(GraphPropertyEnum.IS_DELETED, true);
1156                 props.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name());
1157
1158                 Either<List<GraphVertex>, TitanOperationStatus> componentsToDelete = titanDao.getByCriteria(null, props, JsonParseFlagEnum.NoParse);
1159
1160                 if (componentsToDelete.isRight()) {
1161                         TitanOperationStatus error = componentsToDelete.right().value();
1162                         if (error.equals(TitanOperationStatus.NOT_FOUND)) {
1163                                 log.trace("no components to delete");
1164                                 return Either.left(new ArrayList<>());
1165                         } else {
1166                                 log.info("failed to find components to delete. error : {}", error.name());
1167                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1168                         }
1169                 }
1170                 return Either.left(componentsToDelete.left().value());
1171         }
1172
1173         protected TitanOperationStatus setAdditionalInformationFromGraph(GraphVertex componentV, ToscaElement toscaElement) {
1174                 Either<Map<String, AdditionalInfoParameterDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.ADDITIONAL_INFORMATION);
1175                 if (result.isLeft()) {
1176                         toscaElement.setAdditionalInformation(result.left().value());
1177                 } else {
1178                         if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
1179                                 return result.right().value();
1180                         }
1181                 }
1182                 return TitanOperationStatus.OK;
1183         }
1184
1185         // --------------------------------------------
1186         public abstract <T extends ToscaElement> Either<T, StorageOperationStatus> getToscaElement(String uniqueId, ComponentParametersView componentParametersView);
1187
1188         public abstract <T extends ToscaElement> Either<T, StorageOperationStatus> getToscaElement(GraphVertex toscaElementVertex, ComponentParametersView componentParametersView);
1189
1190         public abstract <T extends ToscaElement> Either<T, StorageOperationStatus> deleteToscaElement(GraphVertex toscaElementVertex);
1191
1192         public abstract <T extends ToscaElement> Either<T, StorageOperationStatus> createToscaElement(ToscaElement toscaElement);
1193
1194         protected abstract <T extends ToscaElement> TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement);
1195
1196         protected abstract <T extends ToscaElement> TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement);
1197
1198         protected abstract <T extends ToscaElement> TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement);
1199
1200         protected abstract <T extends ToscaElement> StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV);
1201
1202         protected abstract <T extends ToscaElement> StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex updateElementV);
1203
1204         public abstract <T extends ToscaElement> void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag);
1205
1206 }