2  * ============LICENSE_START=======================================================
 
   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
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  21 package org.openecomp.sdc.be.model.operations.impl;
 
  23 import java.util.ArrayList;
 
  24 import java.util.HashMap;
 
  25 import java.util.List;
 
  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;
 
  46 @Component("relationship-type-operation")
 
  47 public class RelationshipTypeOperation extends AbstractOperation {
 
  50     private PropertyOperation propertyOperation;
 
  53     private DerivedFromOperation derivedFromOperation;
 
  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 "
 
  58             + "graph status is {}";
 
  59     private static final String FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE = "Failed to fetch properties of "
 
  60             + "relationship type {}";
 
  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);
 
  70             return Either.right(status);
 
  72         return Either.left(result.left().value());
 
  75     public Either<RelationshipTypeDefinition, JanusGraphOperationStatus> getRelationshipTypeByUid(String uniqueId) {
 
  77         Either<RelationshipTypeDefinition, JanusGraphOperationStatus> result;
 
  79         Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
 
  80                 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(
 
  81                         NodeTypeEnum.RelationshipType), uniqueId, RelationshipTypeData.class);
 
  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);
 
  89         RelationshipTypeData relationshipTypeData = relationshipTypesRes.left().value();
 
  90         RelationshipTypeDefinition relationshipTypeDefinition =
 
  91                 new RelationshipTypeDefinition(relationshipTypeData.getRelationshipTypeDataDefinition());
 
  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());
 
 100         if (propertiesStatus.isLeft()) {
 
 101             relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
 
 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);
 
 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());
 
 123         result = Either.left(relationshipTypeDefinition);
 
 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);
 
 140             error = getJanusGraphOperationStatus(relationshipTypeDefinition, error, allPropertiesRes);
 
 143             return Either.left(relationshipTypeDefinition);
 
 145         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error));
 
 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()));
 
 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();
 
 168     private Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllRelationshipTypePropertiesFromAllDerivedFrom(
 
 169             String firstParentType) {
 
 170         return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.RelationshipType,
 
 171                 RelationshipTypeData.class);
 
 174     public Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType(
 
 175             RelationshipTypeDefinition relationshipTypeDefinition,
 
 176             boolean inTransaction) {
 
 178         Either<RelationshipTypeDefinition, StorageOperationStatus> result = null;
 
 181             Either<RelationshipTypeDefinition, StorageOperationStatus> validationRes =
 
 182                     validateUpdateProperties(relationshipTypeDefinition);
 
 183             if (validationRes.isRight()) {
 
 185                         "#addRelationshipType - One or all properties of relationship type {} not valid. status is {}"
 
 186                         , relationshipTypeDefinition, validationRes.right().value());
 
 187                 return validationRes;
 
 190             Either<RelationshipTypeData, StorageOperationStatus> eitherStatus =
 
 191                     addRelationshipTypeToGraph(relationshipTypeDefinition);
 
 193             result = eitherStatus.left()
 
 194                     .map(RelationshipTypeData::getUniqueId)
 
 196                     .bind(uniqueId -> getRelationshipType(uniqueId, inTransaction));
 
 198             if (result.isLeft()) {
 
 199                 logger.debug("#addRelationshipType - The returned RelationshipTypeDefinition is {}",
 
 200                         result.left().value());
 
 205             if (!inTransaction) {
 
 206                 if (result == null || result.isRight()) {
 
 207                     logger.error("#addRelationshipType - Going to execute rollback on graph.");
 
 208                     janusGraphGenericDao.rollback();
 
 210                     logger.debug("#addRelationshipType - Going to execute commit on graph.");
 
 211                     janusGraphGenericDao.commit();
 
 217     public Either<RelationshipTypeDefinition, StorageOperationStatus> getRelationshipType(String uniqueId,
 
 218                                                                                           boolean inTransaction) {
 
 220         Either<RelationshipTypeDefinition, StorageOperationStatus> result;
 
 223             Either<RelationshipTypeDefinition, JanusGraphOperationStatus> ctResult = this.getRelationshipTypeByUid(uniqueId);
 
 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,
 
 231                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
 
 235             result = Either.left(ctResult.left().value());
 
 239             if (!inTransaction) {
 
 240                 logger.debug("Going to execute commit on graph.");
 
 241                 janusGraphGenericDao.commit();
 
 246     private Either<RelationshipTypeData, StorageOperationStatus> addRelationshipTypeToGraph(
 
 247             RelationshipTypeDefinition relationshipTypeDefinition) {
 
 249         logger.debug("Got relationship type {}", relationshipTypeDefinition);
 
 251         String ctUniqueId = UniqueIdBuilder.buildRelationshipTypeUid(relationshipTypeDefinition.getType());
 
 252         RelationshipTypeData relationshipTypeData = buildRelationshipTypeData(relationshipTypeDefinition, ctUniqueId);
 
 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);
 
 259         if (createCTResult.isRight()) {
 
 260             JanusGraphOperationStatus operationStatus = createCTResult.right().value();
 
 261             logger.error("Failed to relationship type {} to graph. status is {}", relationshipTypeDefinition.getType(),
 
 263             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
 
 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()));
 
 277         return addDerivedFromRelation(relationshipTypeDefinition, ctUniqueId)
 
 279                 .map(updatedDerivedFrom -> createCTResult.left().value());
 
 284     private RelationshipTypeData buildRelationshipTypeData(RelationshipTypeDefinition relationshipTypeDefinition,
 
 287         RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition);
 
 289         relationshipTypeData.getRelationshipTypeDataDefinition().setUniqueId(ctUniqueId);
 
 290         Long creationDate = relationshipTypeData.getRelationshipTypeDataDefinition().getCreationTime();
 
 291         if (creationDate == null) {
 
 292             creationDate = System.currentTimeMillis();
 
 294         relationshipTypeData.getRelationshipTypeDataDefinition().setCreationTime(creationDate);
 
 295         relationshipTypeData.getRelationshipTypeDataDefinition().setModificationTime(creationDate);
 
 296         return relationshipTypeData;
 
 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);
 
 307                 "#addDerivedFromRelation - adding derived from relation between relationship type {} to its parent "
 
 308                         + "{}", relationshipTypeDefinition.getType(), derivedFrom);
 
 309         return getRelationshipTypeByType(derivedFrom)
 
 311                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
 
 313                 .bind(derivedFromRelationship -> derivedFromOperation.addDerivedFromRelation(relationshipTypeUniqueId,
 
 314                         derivedFromRelationship.getUniqueId(), NodeTypeEnum.RelationshipType));
 
 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);
 
 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;
 
 330             updateRelationshipEither =
 
 331                     updateRelationshipTypeOnGraph(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
 
 333             if (!inTransaction) {
 
 334                 if (updateRelationshipEither == null || updateRelationshipEither.isRight()) {
 
 335                     janusGraphGenericDao.rollback();
 
 337                     janusGraphGenericDao.commit();
 
 341         return updateRelationshipEither;
 
 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)
 
 351                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
 
 353                 .bind(updatedNode -> updateRelationshipTypeProperties(newRelationshipTypeDefinition.getUniqueId(),
 
 354                         newRelationshipTypeDefinition.getProperties()))
 
 356                 .bind(updatedProperties -> updateRelationshipTypeDerivedFrom(newRelationshipTypeDefinition,
 
 357                         oldRelationshipTypeDefinition.getDerivedFrom()))
 
 359                 .map(updatedDerivedFrom -> newRelationshipTypeDefinition);
 
 362     private Either<Map<String, PropertyData>, StorageOperationStatus> updateRelationshipTypeProperties(
 
 363             String relationshipTypeId, Map<String, PropertyDefinition> properties) {
 
 365                 "#updateRelationshipTypeProperties - updating relationship type properties for relationship type with "
 
 366                         + "id {}", relationshipTypeId);
 
 367         return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.RelationshipType, relationshipTypeId)
 
 369                 .bind(deleteProps -> addPropertiesToRelationshipType(relationshipTypeId, properties));
 
 372     private Either<GraphRelation, StorageOperationStatus> updateRelationshipTypeDerivedFrom(
 
 373             RelationshipTypeDefinition newRelationshipTypeDefinition, String currDerivedFromRelationshipType) {
 
 374         String relationshipTypeId = newRelationshipTypeDefinition.getUniqueId();
 
 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);
 
 384         return addDerivedFromRelation(newRelationshipTypeDefinition, relationshipTypeId);
 
 387     private void updateRelationshipTypeData(RelationshipTypeDefinition newRelationshipTypeDefinition,
 
 388                                             RelationshipTypeDefinition oldRelationshipTypeDefinition) {
 
 389         newRelationshipTypeDefinition.setUniqueId(oldRelationshipTypeDefinition.getUniqueId());
 
 390         newRelationshipTypeDefinition.setCreationTime(oldRelationshipTypeDefinition.getCreationTime());
 
 391         newRelationshipTypeDefinition.setModificationTime(System.currentTimeMillis());
 
 394     private Either<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToRelationshipType(
 
 395             String relationshipTypeId, Map<String, PropertyDefinition> properties) {
 
 397                 "#addPropertiesToRelationshipType - adding relationship type properties for relationship type with "
 
 398                         + "id {}", relationshipTypeId);
 
 399         return propertyOperation
 
 400                 .addPropertiesToElementType(relationshipTypeId, NodeTypeEnum.RelationshipType, properties)
 
 402                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
 
 405     private StorageOperationStatus deleteDerivedFromRelationshipType(String relationshipTypeId,
 
 406                                                                      String derivedFromType) {
 
 407         if (derivedFromType == null) {
 
 408             return StorageOperationStatus.OK;
 
 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);
 
 419     public Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getAllRelationshipTypes() {
 
 421         Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap = new HashMap<>();
 
 422         Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> result = Either.left(relationshipTypeDefinitionMap);
 
 424         Either<List<RelationshipTypeData>, JanusGraphOperationStatus> getAllRelationshipTypes =
 
 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);
 
 436         List<RelationshipTypeData> list = getAllRelationshipTypes.left().value();
 
 439             logger.trace("Number of relationship types to load is {}", list.size());
 
 441             Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> status =
 
 442                     getMapJanusGraphOperationStatusEither(relationshipTypeDefinitionMap, list);
 
 443             if (status != null) {
 
 451     private Either<Map<String, RelationshipTypeDefinition>, JanusGraphOperationStatus> getMapJanusGraphOperationStatusEither(
 
 452             Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap,
 
 453             List<RelationshipTypeData> list) {
 
 454         for (RelationshipTypeData relationshipTypeData : list) {
 
 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;
 
 466                 return Either.right(status);
 
 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));
 
 478         Either<RelationshipTypeData, JanusGraphOperationStatus> relationshipTypesRes =
 
 479                 janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
 
 480                         RelationshipTypeData.class);
 
 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);
 
 488         RelationshipTypeData ctData = relationshipTypesRes.left().value();
 
 489         RelationshipTypeDefinition relationshipTypeDefinition =
 
 490                 new RelationshipTypeDefinition(ctData.getRelationshipTypeDataDefinition());
 
 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());
 
 499         if (propertiesStatus.isLeft()) {
 
 500             relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
 
 503         fillDerivedFrom(uniqueId, relationshipTypeDefinition);
 
 505         relationshipTypeDefinitionMap.put(relationshipTypeDefinition.getType(), relationshipTypeDefinition);
 
 507         return Either.left(relationshipTypeDefinition);
 
 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)
 
 515                 .bind(this::handleDerivedFromNotExist)
 
 517                 .map(derivedFrom -> setDerivedFrom(relationshipType, derivedFrom));
 
 521     private Either<RelationshipTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
 
 522         if (err == StorageOperationStatus.NOT_FOUND) {
 
 523             return Either.left(null);
 
 525         return Either.right(err);
 
 528     private RelationshipTypeData setDerivedFrom(RelationshipTypeDefinition relationshipTypeDefinition, RelationshipTypeData derivedFrom) {
 
 529         if (derivedFrom != null) {
 
 530             relationshipTypeDefinition.setDerivedFrom(derivedFrom.getRelationshipTypeDataDefinition().getType());