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