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