Added oparent to sdc main
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / RelationshipTypeOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 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.operations.impl;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import fj.data.Either;
29 import org.apache.commons.collections.MapUtils;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
32 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
33 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
34 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
35 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
36 import org.openecomp.sdc.be.model.PropertyDefinition;
37 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
38 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.openecomp.sdc.be.resources.data.PropertyData;
41 import org.openecomp.sdc.be.resources.data.RelationshipTypeData;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.springframework.beans.factory.annotation.Autowired;
44 import org.springframework.stereotype.Component;
45
46 @Component("relationship-type-operation")
47 public class RelationshipTypeOperation extends AbstractOperation {
48
49     @Autowired
50     private PropertyOperation propertyOperation;
51
52     @Autowired
53     private DerivedFromOperation derivedFromOperation;
54
55     private static final Logger logger = Logger.getLogger(RelationshipTypeOperation.class.getName());
56     private static final String RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Relationship type {} cannot be "
57             + "found in "
58             + "graph status is {}";
59     private static final String FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE = "Failed to fetch properties of "
60             + "relationship type {}";
61
62     public Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByName(String name) {
63         String uid = UniqueIdBuilder.buildRelationshipTypeUid(name);
64         Either<RelationshipTypeDefinition, JanusGraphOperationStatus> result = getRelationshipTypeByUid(uid);
65         if (result.isRight()) {
66             JanusGraphOperationStatus status = result.right().value();
67             if (status != JanusGraphOperationStatus.NOT_FOUND) {
68                 logger.error("Failed to get information on relationship type {} status is {}", name, status);
69             }
70             return Either.right(status);
71         }
72         return Either.left(result.left().value());
73     }
74
75     public Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByUid(String uniqueId) {
76
77         Either<RelationshipTypeDefinition, JanusGraphOperationStatus> result;
78
79         Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
80                 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(
81                         NodeTypeEnum.RelationshipType), uniqueId, RelationshipTypeData.class);
82
83         if (relationshipTypesRes.isRight()) {
84             JanusGraphOperationStatus status = relationshipTypesRes.right().value();
85             logger.debug("Relationship type {} cannot be found in graph. status is {}", uniqueId, status);
86             return Either.right(status);
87         }
88
89         RelationshipTypeData relationshipTypeData = relationshipTypesRes.left().value();
90         RelationshipTypeDefinition relationshipTypeDefinition =
91                 new RelationshipTypeDefinition(relationshipTypeData.getRelationshipTypeDataDefinition());
92
93         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus =
94                 OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
95         if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
96             logger.error("Failed to fetch properties of relationship type {}", uniqueId);
97             return Either.right(propertiesStatus.right().value());
98         }
99
100         if (propertiesStatus.isLeft()) {
101             relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
102         }
103
104         Either<ImmutablePair<RelationshipTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
105                 .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
106                         GraphEdgeLabels.DERIVED_FROM,
107                         NodeTypeEnum.RelationshipType, RelationshipTypeData.class);
108         logger.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
109         if (parentNode.isRight()) {
110             JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
111             if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
112                 logger.error("Failed to find the parent relationship of relationship type {}. status is {}", uniqueId,
113                     janusGraphOperationStatus);
114                 result = Either.right(janusGraphOperationStatus);
115                 return result;
116             }
117         } else {
118             // derived from node was found
119             ImmutablePair<RelationshipTypeData, GraphEdge> immutablePair = parentNode.left().value();
120             RelationshipTypeData parentCT = immutablePair.getKey();
121             relationshipTypeDefinition.setDerivedFrom(parentCT.getRelationshipTypeDataDefinition().getType());
122         }
123         result = Either.left(relationshipTypeDefinition);
124
125         return result;
126     }
127
128     private Either<RelationshipTypeDefinition, StorageOperationStatus> validateUpdateProperties(
129             RelationshipTypeDefinition relationshipTypeDefinition) {
130         JanusGraphOperationStatus error = null;
131         if (MapUtils.isNotEmpty(relationshipTypeDefinition.getProperties())
132                 && relationshipTypeDefinition.getDerivedFrom() != null) {
133             Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesRes =
134                     getAllRelationshipTypePropertiesFromAllDerivedFrom(relationshipTypeDefinition.getDerivedFrom());
135             if (allPropertiesRes.isRight() && !JanusGraphOperationStatus.NOT_FOUND.equals(allPropertiesRes.right().value())) {
136                 error = allPropertiesRes.right().value();
137                 logger.debug("Couldn't fetch derived from property nodes for relationship type {}, error: {}",
138                         relationshipTypeDefinition.getType(), error);
139             }
140             error = getJanusGraphOperationStatus(relationshipTypeDefinition, error, allPropertiesRes);
141         }
142         if (error == null) {
143             return Either.left(relationshipTypeDefinition);
144         }
145         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error));
146     }
147
148     private JanusGraphOperationStatus getJanusGraphOperationStatus(RelationshipTypeDefinition relationshipTypeDefinition,
149                                                               JanusGraphOperationStatus error,
150                                                               Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesRes) {
151         if (error == null && !allPropertiesRes.left().value().isEmpty()) {
152             Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value();
153             relationshipTypeDefinition.getProperties().entrySet().stream()
154                     .filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null)
155                     .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType()));
156
157             List<PropertyDefinition>
158                     properties = new ArrayList<>(relationshipTypeDefinition.getProperties().values());
159             Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesRes =
160                     propertyOperation.validatePropertiesUniqueness(allPropertiesRes.left().value(), properties);
161             if (validatePropertiesRes.isRight()) {
162                 error = validatePropertiesRes.right().value();
163             }
164         }
165         return error;
166     }
167
168     private Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllRelationshipTypePropertiesFromAllDerivedFrom(
169             String firstParentType) {
170         return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.RelationshipType,
171                 RelationshipTypeData.class);
172     }
173
174     public Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType(
175             RelationshipTypeDefinition relationshipTypeDefinition,
176             boolean inTransaction) {
177
178         Either<RelationshipTypeDefinition, StorageOperationStatus> result = null;
179
180         try {
181             Either<RelationshipTypeDefinition, StorageOperationStatus> validationRes =
182                     validateUpdateProperties(relationshipTypeDefinition);
183             if (validationRes.isRight()) {
184                 logger.error(
185                         "#addRelationshipType - One or all properties of relationship type {} not valid. status is {}"
186                         , relationshipTypeDefinition, validationRes.right().value());
187                 return validationRes;
188             }
189
190             Either<RelationshipTypeData, StorageOperationStatus> eitherStatus =
191                     addRelationshipTypeToGraph(relationshipTypeDefinition);
192
193             result = eitherStatus.left()
194                     .map(RelationshipTypeData::getUniqueId)
195                     .left()
196                     .bind(uniqueId -> getRelationshipType(uniqueId, inTransaction));
197
198             if (result.isLeft()) {
199                 logger.debug("#addRelationshipType - The returned RelationshipTypeDefinition is {}",
200                         result.left().value());
201             }
202
203             return result;
204         } finally {
205             if (!inTransaction) {
206                 if (result == null || result.isRight()) {
207                     logger.error("#addRelationshipType - Going to execute rollback on graph.");
208                     janusGraphGenericDao.rollback();
209                 } else {
210                     logger.debug("#addRelationshipType - Going to execute commit on graph.");
211                     janusGraphGenericDao.commit();
212                 }
213             }
214         }
215     }
216
217     public Either<RelationshipTypeDefinition, StorageOperationStatus> getRelationshipType(String uniqueId,
218                                                                                           boolean inTransaction) {
219
220         Either<RelationshipTypeDefinition, StorageOperationStatus> result;
221         try {
222
223             Either<RelationshipTypeDefinition, JanusGraphOperationStatus> ctResult = this.getRelationshipTypeByUid(uniqueId);
224
225             if (ctResult.isRight()) {
226                 JanusGraphOperationStatus status = ctResult.right().value();
227                 if (status != JanusGraphOperationStatus.NOT_FOUND) {
228                     logger.error("Failed to retrieve information on relationship type {}. status is {}", uniqueId,
229                             status);
230                 }
231                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
232                 return result;
233             }
234
235             result = Either.left(ctResult.left().value());
236
237             return result;
238         } finally {
239             if (!inTransaction) {
240                 logger.debug("Going to execute commit on graph.");
241                 janusGraphGenericDao.commit();
242             }
243         }
244     }
245
246     private Either<RelationshipTypeData, StorageOperationStatus> addRelationshipTypeToGraph(
247             RelationshipTypeDefinition relationshipTypeDefinition) {
248
249         logger.debug("Got relationship type {}", relationshipTypeDefinition);
250
251         String ctUniqueId = UniqueIdBuilder.buildRelationshipTypeUid(relationshipTypeDefinition.getType());
252         RelationshipTypeData relationshipTypeData = buildRelationshipTypeData(relationshipTypeDefinition, ctUniqueId);
253
254         logger.debug("Before adding relationship type to graph. relationshipTypeData = {}", relationshipTypeData);
255         Either<RelationshipTypeData, JanusGraphOperationStatus> createCTResult =
256                 janusGraphGenericDao.createNode(relationshipTypeData, RelationshipTypeData.class);
257         logger.debug("After adding relationship type to graph. status is = {}", createCTResult);
258
259         if (createCTResult.isRight()) {
260             JanusGraphOperationStatus operationStatus = createCTResult.right().value();
261             logger.error("Failed to relationship type {} to graph. status is {}", relationshipTypeDefinition.getType(),
262                     operationStatus);
263             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
264         }
265
266         RelationshipTypeData resultCTD = createCTResult.left().value();
267         Map<String, PropertyDefinition> propertiesMap = relationshipTypeDefinition.getProperties();
268         Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToRelationshipType = propertyOperation
269                 .addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.RelationshipType, propertiesMap);
270         if (addPropertiesToRelationshipType.isRight()) {
271             logger.error("Failed add properties {} to relationship {}", propertiesMap,
272                     relationshipTypeDefinition.getType());
273             return Either.right(DaoStatusConverter
274                     .convertJanusGraphStatusToStorageStatus(addPropertiesToRelationshipType.right().value()));
275         }
276
277         return addDerivedFromRelation(relationshipTypeDefinition, ctUniqueId)
278                 .left()
279                 .map(updatedDerivedFrom -> createCTResult.left().value());
280
281
282     }
283
284     private RelationshipTypeData buildRelationshipTypeData(RelationshipTypeDefinition relationshipTypeDefinition,
285                                                            String ctUniqueId) {
286
287         RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition);
288
289         relationshipTypeData.getRelationshipTypeDataDefinition().setUniqueId(ctUniqueId);
290         Long creationDate = relationshipTypeData.getRelationshipTypeDataDefinition().getCreationTime();
291         if (creationDate == null) {
292             creationDate = System.currentTimeMillis();
293         }
294         relationshipTypeData.getRelationshipTypeDataDefinition().setCreationTime(creationDate);
295         relationshipTypeData.getRelationshipTypeDataDefinition().setModificationTime(creationDate);
296         return relationshipTypeData;
297     }
298
299     private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(
300             RelationshipTypeDefinition relationshipTypeDefinition,
301             String relationshipTypeUniqueId) {
302         String derivedFrom = relationshipTypeDefinition.getDerivedFrom();
303         if (derivedFrom == null) {
304             return Either.left(null);
305         }
306         logger.debug(
307                 "#addDerivedFromRelation - adding derived from relation between relationship type {} to its parent "
308                         + "{}", relationshipTypeDefinition.getType(), derivedFrom);
309         return getRelationshipTypeByType(derivedFrom)
310                 .right()
311                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
312                 .left()
313                 .bind(derivedFromRelationship -> derivedFromOperation.addDerivedFromRelation(relationshipTypeUniqueId,
314                         derivedFromRelationship.getUniqueId(), NodeTypeEnum.RelationshipType));
315     }
316
317     private Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByType(
318             String relationshipType) {
319         // Optimization: In case of Relationship Type its unique ID is the same as type
320         return getRelationshipTypeByUid(relationshipType);
321     }
322
323     public Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipType(
324             RelationshipTypeDefinition newRelationshipTypeDefinition,
325             RelationshipTypeDefinition oldRelationshipTypeDefinition, boolean inTransaction) {
326         logger.debug("updating relationship type {}", newRelationshipTypeDefinition.getType());
327         Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipEither = null;
328
329         try {
330             updateRelationshipEither =
331                     updateRelationshipTypeOnGraph(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
332         } finally {
333             if (!inTransaction) {
334                 if (updateRelationshipEither == null || updateRelationshipEither.isRight()) {
335                     janusGraphGenericDao.rollback();
336                 } else {
337                     janusGraphGenericDao.commit();
338                 }
339             }
340         }
341         return updateRelationshipEither;
342     }
343
344     private Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipTypeOnGraph(
345             RelationshipTypeDefinition newRelationshipTypeDefinition,
346             RelationshipTypeDefinition oldRelationshipTypeDefinition) {
347         updateRelationshipTypeData(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
348         return janusGraphGenericDao
349                 .updateNode(new RelationshipTypeData(newRelationshipTypeDefinition), RelationshipTypeData.class)
350                 .right()
351                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
352                 .left()
353                 .bind(updatedNode -> updateRelationshipTypeProperties(newRelationshipTypeDefinition.getUniqueId(),
354                         newRelationshipTypeDefinition.getProperties()))
355                 .left()
356                 .bind(updatedProperties -> updateRelationshipTypeDerivedFrom(newRelationshipTypeDefinition,
357                         oldRelationshipTypeDefinition.getDerivedFrom()))
358                 .left()
359                 .map(updatedDerivedFrom -> newRelationshipTypeDefinition);
360     }
361
362     private Either<Map<String, PropertyData>, StorageOperationStatus> updateRelationshipTypeProperties(
363             String relationshipTypeId, Map<String, PropertyDefinition> properties) {
364         logger.debug(
365                 "#updateRelationshipTypeProperties - updating relationship type properties for relationship type with "
366                         + "id {}", relationshipTypeId);
367         return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.RelationshipType, relationshipTypeId)
368                 .left()
369                 .bind(deleteProps -> addPropertiesToRelationshipType(relationshipTypeId, properties));
370     }
371
372     private Either<GraphRelation, StorageOperationStatus> updateRelationshipTypeDerivedFrom(
373             RelationshipTypeDefinition newRelationshipTypeDefinition, String currDerivedFromRelationshipType) {
374         String relationshipTypeId = newRelationshipTypeDefinition.getUniqueId();
375         logger.debug(
376                 "#updateRelationshipTypeDerivedFrom - updating relationship derived from relation for relationship "
377                         + "type with id {}. old derived type {}. new derived type {}", relationshipTypeId,
378                 currDerivedFromRelationshipType, newRelationshipTypeDefinition.getDerivedFrom());
379         StorageOperationStatus deleteDerivedRelationStatus =
380                 deleteDerivedFromRelationshipType(relationshipTypeId, currDerivedFromRelationshipType);
381         if (deleteDerivedRelationStatus != StorageOperationStatus.OK) {
382             return Either.right(deleteDerivedRelationStatus);
383         }
384         return addDerivedFromRelation(newRelationshipTypeDefinition, relationshipTypeId);
385     }
386
387     private void updateRelationshipTypeData(RelationshipTypeDefinition newRelationshipTypeDefinition,
388                                             RelationshipTypeDefinition oldRelationshipTypeDefinition) {
389         newRelationshipTypeDefinition.setUniqueId(oldRelationshipTypeDefinition.getUniqueId());
390         newRelationshipTypeDefinition.setCreationTime(oldRelationshipTypeDefinition.getCreationTime());
391         newRelationshipTypeDefinition.setModificationTime(System.currentTimeMillis());
392     }
393
394     private Either<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToRelationshipType(
395             String relationshipTypeId, Map<String, PropertyDefinition> properties) {
396         logger.debug(
397                 "#addPropertiesToRelationshipType - adding relationship type properties for relationship type with "
398                         + "id {}", relationshipTypeId);
399         return propertyOperation
400                 .addPropertiesToElementType(relationshipTypeId, NodeTypeEnum.RelationshipType, properties)
401                 .right()
402                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
403     }
404
405     private StorageOperationStatus deleteDerivedFromRelationshipType(String relationshipTypeId,
406                                                                      String derivedFromType) {
407         if (derivedFromType == null) {
408             return StorageOperationStatus.OK;
409         }
410         logger.debug("#deleteDerivedFromRelationshipType - deleting derivedFrom relation for relationship type with id "
411                 + "{} and its derived type {}", relationshipTypeId, derivedFromType);
412         return getRelationshipTypeByType(derivedFromType)
413                 .either(derivedFromNode -> derivedFromOperation
414                                 .removeDerivedFromRelation(relationshipTypeId, derivedFromNode.getUniqueId(),
415                                         NodeTypeEnum.RelationshipType),
416                         DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
417     }
418
419     public Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getAllRelationshipTypes() {
420
421         Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap = new HashMap<>();
422         Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> result = Either.left(relationshipTypeDefinitionMap);
423
424         Either<List<RelationshipTypeData>, JanusGraphOperationStatus> getAllRelationshipTypes =
425                 janusGraphGenericDao
426                     .getByCriteria(NodeTypeEnum.RelationshipType, null, RelationshipTypeData.class);
427         if (getAllRelationshipTypes.isRight()) {
428             JanusGraphOperationStatus status = getAllRelationshipTypes.right().value();
429             if (status != JanusGraphOperationStatus.NOT_FOUND) {
430                 return Either.right(status);
431             } else {
432                 return result;
433             }
434         }
435
436         List<RelationshipTypeData> list = getAllRelationshipTypes.left().value();
437         if (list != null) {
438
439             logger.trace("Number of relationship types to load is {}", list.size());
440             //Set properties
441             Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> status =
442                     getMapJanusGraphOperationStatusEither(relationshipTypeDefinitionMap, list);
443             if (status != null) {
444                 return status;
445             }
446         }
447
448         return result;
449     }
450
451     private Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getMapJanusGraphOperationStatusEither(
452             Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap,
453             List<RelationshipTypeData> list) {
454         for (RelationshipTypeData relationshipTypeData : list) {
455
456             logger.trace("Going to fetch relationship type {}. uid is {}",
457                     relationshipTypeData.getRelationshipTypeDataDefinition().getType(),
458                     relationshipTypeData.getUniqueId());
459             Either<RelationshipTypeDefinition, JanusGraphOperationStatus> relationshipTypesByUid =
460                     getAndAddPropertiesANdDerivedFrom(relationshipTypeData.getUniqueId(), relationshipTypeDefinitionMap);
461             if (relationshipTypesByUid.isRight()) {
462                 JanusGraphOperationStatus status = relationshipTypesByUid.right().value();
463                 if (status == JanusGraphOperationStatus.NOT_FOUND) {
464                     status = JanusGraphOperationStatus.INVALID_ID;
465                 }
466                 return Either.right(status);
467             }
468         }
469         return null;
470     }
471
472     private Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getAndAddPropertiesANdDerivedFrom(
473             String uniqueId, Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap) {
474         if (relationshipTypeDefinitionMap.containsKey(uniqueId)) {
475             return Either.left(relationshipTypeDefinitionMap.get(uniqueId));
476         }
477
478         Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
479                 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
480                         RelationshipTypeData.class);
481
482         if (relationshipTypesRes.isRight()) {
483             JanusGraphOperationStatus status = relationshipTypesRes.right().value();
484             logger.debug(RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
485             return Either.right(status);
486         }
487
488         RelationshipTypeData ctData = relationshipTypesRes.left().value();
489         RelationshipTypeDefinition relationshipTypeDefinition =
490                 new RelationshipTypeDefinition(ctData.getRelationshipTypeDataDefinition());
491
492         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus =
493                 OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
494         if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
495             logger.error(FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE, uniqueId);
496             return Either.right(propertiesStatus.right().value());
497         }
498
499         if (propertiesStatus.isLeft()) {
500             relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
501         }
502
503         fillDerivedFrom(uniqueId, relationshipTypeDefinition);
504
505         relationshipTypeDefinitionMap.put(relationshipTypeDefinition.getType(), relationshipTypeDefinition);
506
507         return Either.left(relationshipTypeDefinition);
508     }
509
510     private void fillDerivedFrom(String uniqueId,
511                                  RelationshipTypeDefinition relationshipType) {
512         logger.debug("#fillDerivedFrom - fetching relationship type {} derived node", relationshipType.getType());
513         derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.RelationshipType, RelationshipTypeData.class)
514                 .right()
515                 .bind(this::handleDerivedFromNotExist)
516                 .left()
517                 .map(derivedFrom -> setDerivedFrom(relationshipType, derivedFrom));
518
519     }
520
521     private Either<RelationshipTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
522         if (err == StorageOperationStatus.NOT_FOUND) {
523             return Either.left(null);
524         }
525         return Either.right(err);
526     }
527
528     private RelationshipTypeData setDerivedFrom(RelationshipTypeDefinition relationshipTypeDefinition, RelationshipTypeData derivedFrom) {
529         if (derivedFrom != null) {
530             relationshipTypeDefinition.setDerivedFrom(derivedFrom.getRelationshipTypeDataDefinition().getType());
531         }
532         return derivedFrom;
533     }
534 }