Reformat catalog-model
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / CapabilityTypeOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.model.operations.impl;
21
22 import fj.data.Either;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.stream.Collectors;
27 import org.apache.commons.collections.MapUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
31 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
32 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
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.CapabilityTypeDefinition;
37 import org.openecomp.sdc.be.model.PropertyDefinition;
38 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
39 import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation;
40 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
41 import org.openecomp.sdc.be.model.operations.api.TypeOperations;
42 import org.openecomp.sdc.be.resources.data.CapabilityTypeData;
43 import org.openecomp.sdc.be.resources.data.PropertyData;
44 import org.openecomp.sdc.common.log.wrappers.Logger;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.stereotype.Component;
47
48 @Component("capability-type-operation")
49 public class CapabilityTypeOperation extends AbstractOperation implements ICapabilityTypeOperation {
50
51     private static final Logger log = Logger.getLogger(CapabilityTypeOperation.class.getName());
52     private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph." + " status is {}";
53     private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
54     @Autowired
55     private PropertyOperation propertyOperation;
56     @Autowired
57     private DerivedFromOperation derivedFromOperation;
58
59     public CapabilityTypeOperation() {
60         super();
61     }
62
63     /**
64      * FOR TEST ONLY
65      *
66      * @param janusGraphGenericDao
67      */
68     public void setJanusGraphGenericDao(HealingJanusGraphGenericDao janusGraphGenericDao) {
69         this.janusGraphGenericDao = janusGraphGenericDao;
70     }
71
72     @Override
73     public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition,
74                                                                                       boolean inTransaction) {
75         Either<CapabilityTypeDefinition, StorageOperationStatus> result = null;
76         try {
77             Either<CapabilityTypeDefinition, StorageOperationStatus> validationRes = validateUpdateProperties(capabilityTypeDefinition);
78             if (validationRes.isRight()) {
79                 log.error("#addCapabilityType - One or all properties of capability type {} not valid. status is {}", capabilityTypeDefinition,
80                     validationRes.right().value());
81                 return result;
82             }
83             Either<CapabilityTypeData, StorageOperationStatus> eitherStatus = addCapabilityTypeToGraph(capabilityTypeDefinition);
84             result = eitherStatus.left().map(CapabilityTypeData::getUniqueId).left().bind(uniqueId -> getCapabilityType(uniqueId, inTransaction));
85             if (result.isLeft()) {
86                 log.debug("#addCapabilityType - The returned CapabilityTypeDefinition is {}", result.left().value());
87             }
88             return result;
89         } finally {
90             if (!inTransaction) {
91                 if (result == null || result.isRight()) {
92                     log.error("#addCapabilityType - Going to execute rollback on graph.");
93                     janusGraphGenericDao.rollback();
94                 } else {
95                     log.debug("#addCapabilityType - Going to execute commit on graph.");
96                     janusGraphGenericDao.commit();
97                 }
98             }
99         }
100     }
101
102     public Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> getAllCapabilityTypePropertiesFromAllDerivedFrom(
103         String firstParentType) {
104         return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.CapabilityType, CapabilityTypeData.class);
105     }
106
107     public Either<CapabilityTypeDefinition, StorageOperationStatus> validateUpdateProperties(CapabilityTypeDefinition capabilityTypeDefinition) {
108         JanusGraphOperationStatus error = null;
109         if (MapUtils.isNotEmpty(capabilityTypeDefinition.getProperties()) && capabilityTypeDefinition.getDerivedFrom() != null) {
110             Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> allPropertiesRes = getAllCapabilityTypePropertiesFromAllDerivedFrom(
111                 capabilityTypeDefinition.getDerivedFrom());
112             if (allPropertiesRes.isRight() && !allPropertiesRes.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
113                 error = allPropertiesRes.right().value();
114                 log.debug("Couldn't fetch derived from property nodes for capability type {}, error: {}", capabilityTypeDefinition.getType(), error);
115             }
116             if (error == null && !allPropertiesRes.left().value().isEmpty()) {
117                 Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value();
118                 capabilityTypeDefinition.getProperties().entrySet().stream()
119                     .filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null)
120                     .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType()));
121                 List<PropertyDefinition> properties = capabilityTypeDefinition.getProperties().values().stream().collect(Collectors.toList());
122                 Either<List<PropertyDefinition>, JanusGraphOperationStatus> validatePropertiesRes = propertyOperation
123                     .validatePropertiesUniqueness(allPropertiesRes.left().value(), properties);
124                 if (validatePropertiesRes.isRight()) {
125                     error = validatePropertiesRes.right().value();
126                 }
127             }
128         }
129         if (error == null) {
130             return Either.left(capabilityTypeDefinition);
131         }
132         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error));
133     }
134
135     /**
136      * Add capability type to graph.
137      * <p>
138      * 1. Add capability type node
139      * <p>
140      * 2. Add edge between the former node to its parent(if exists)
141      * <p>
142      * 3. Add property node and associate it to the node created at #1. (per property & if exists)
143      *
144      * @param capabilityTypeDefinition
145      * @return
146      */
147     private Either<CapabilityTypeData, StorageOperationStatus> addCapabilityTypeToGraph(CapabilityTypeDefinition capabilityTypeDefinition) {
148         log.debug("Got capability type {}", capabilityTypeDefinition);
149         String ctUniqueId = UniqueIdBuilder.buildCapabilityTypeUid(capabilityTypeDefinition.getType());
150         CapabilityTypeData capabilityTypeData = buildCapabilityTypeData(capabilityTypeDefinition, ctUniqueId);
151         log.debug("Before adding capability type to graph. capabilityTypeData = {}", capabilityTypeData);
152         Either<CapabilityTypeData, JanusGraphOperationStatus> createCTResult = janusGraphGenericDao
153             .createNode(capabilityTypeData, CapabilityTypeData.class);
154         log.debug("After adding capability type to graph. status is = {}", createCTResult);
155         if (createCTResult.isRight()) {
156             JanusGraphOperationStatus operationStatus = createCTResult.right().value();
157             log.error("Failed to capability type {} to graph. status is {}", capabilityTypeDefinition.getType(), operationStatus);
158             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
159         }
160         CapabilityTypeData resultCTD = createCTResult.left().value();
161         Map<String, PropertyDefinition> propertiesMap = capabilityTypeDefinition.getProperties();
162         Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToCapablityType = propertyOperation
163             .addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.CapabilityType, propertiesMap);
164         if (addPropertiesToCapablityType.isRight()) {
165             log.error("Failed add properties {} to capability {}", propertiesMap, capabilityTypeDefinition.getType());
166             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToCapablityType.right().value()));
167         }
168         return addDerivedFromRelation(capabilityTypeDefinition, ctUniqueId).left().map(updatedDerivedFrom -> createCTResult.left().value());
169     }
170
171     private CapabilityTypeData buildCapabilityTypeData(CapabilityTypeDefinition capabilityTypeDefinition, String ctUniqueId) {
172         CapabilityTypeData capabilityTypeData = new CapabilityTypeData(capabilityTypeDefinition);
173         capabilityTypeData.getCapabilityTypeDataDefinition().setUniqueId(ctUniqueId);
174         Long creationDate = capabilityTypeData.getCapabilityTypeDataDefinition().getCreationTime();
175         if (creationDate == null) {
176             creationDate = System.currentTimeMillis();
177         }
178         capabilityTypeData.getCapabilityTypeDataDefinition().setCreationTime(creationDate);
179         capabilityTypeData.getCapabilityTypeDataDefinition().setModificationTime(creationDate);
180         return capabilityTypeData;
181     }
182
183     @Override
184     public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId, boolean inTransaction) {
185         Either<CapabilityTypeDefinition, StorageOperationStatus> result = null;
186         try {
187             Either<CapabilityTypeDefinition, JanusGraphOperationStatus> ctResult = this.getCapabilityTypeByUid(uniqueId);
188             if (ctResult.isRight()) {
189                 JanusGraphOperationStatus status = ctResult.right().value();
190                 if (status != JanusGraphOperationStatus.NOT_FOUND) {
191                     log.error("Failed to retrieve information on capability type {}. status is {}", uniqueId, status);
192                 }
193                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(ctResult.right().value()));
194                 return result;
195             }
196             result = Either.left(ctResult.left().value());
197             return result;
198         } finally {
199             if (!inTransaction) {
200                 log.debug("Going to execute commit on graph.");
201                 janusGraphGenericDao.commit();
202             }
203         }
204     }
205
206     public Either<CapabilityTypeDefinition, JanusGraphOperationStatus> getCapabilityTypeByType(String capabilityType) {
207         // Optimization: In case of Capability Type its unique ID is the same as type
208         return getCapabilityTypeByUid(capabilityType);
209     }
210
211     /**
212      * Build Capability type object from graph by unique id
213      *
214      * @param uniqueId
215      * @return
216      */
217     public Either<CapabilityTypeDefinition, JanusGraphOperationStatus> getCapabilityTypeByUid(String uniqueId) {
218         Either<CapabilityTypeDefinition, JanusGraphOperationStatus> result = null;
219         Either<CapabilityTypeData, JanusGraphOperationStatus> capabilityTypesRes = janusGraphGenericDao
220             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, CapabilityTypeData.class);
221         if (capabilityTypesRes.isRight()) {
222             JanusGraphOperationStatus status = capabilityTypesRes.right().value();
223             log.debug("Capability type {} cannot be found in graph. status is {}", uniqueId, status);
224             return Either.right(status);
225         }
226         CapabilityTypeData ctData = capabilityTypesRes.left().value();
227         CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition());
228         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus = OperationUtils
229             .fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType);
230         if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
231             log.error("Failed to fetch properties of capability type {}", uniqueId);
232             return Either.right(propertiesStatus.right().value());
233         }
234         if (propertiesStatus.isLeft()) {
235             capabilityTypeDefinition.setProperties(propertiesStatus.left().value());
236         }
237         Either<ImmutablePair<CapabilityTypeData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao
238             .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, GraphEdgeLabels.DERIVED_FROM,
239                 NodeTypeEnum.CapabilityType, CapabilityTypeData.class);
240         log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
241         if (parentNode.isRight()) {
242             JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
243             if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
244                 log.error("Failed to find the parent capability of capability type {}. status is {}", uniqueId, janusGraphOperationStatus);
245                 result = Either.right(janusGraphOperationStatus);
246                 return result;
247             }
248         } else {
249             // derived from node was found
250             ImmutablePair<CapabilityTypeData, GraphEdge> immutablePair = parentNode.left().value();
251             CapabilityTypeData parentCT = immutablePair.getKey();
252             capabilityTypeDefinition.setDerivedFrom(parentCT.getCapabilityTypeDataDefinition().getType());
253         }
254         result = Either.left(capabilityTypeDefinition);
255         return result;
256     }
257
258     public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) {
259         return derivedFromOperation
260             .isTypeDerivedFrom(childCandidateType, parentCandidateType, null, NodeTypeEnum.CapabilityType, CapabilityTypeData.class,
261                 t -> t.getCapabilityTypeDataDefinition().getType());
262     }
263
264     @Override
265     public Either<CapabilityTypeDefinition, StorageOperationStatus> updateCapabilityType(CapabilityTypeDefinition capabilityTypeDefNew,
266                                                                                          CapabilityTypeDefinition capabilityTypeDefOld) {
267         log.debug("updating capability type {}", capabilityTypeDefNew.getType());
268         updateCapabilityTypeData(capabilityTypeDefNew, capabilityTypeDefOld);
269         return updateCapabilityTypeOnGraph(capabilityTypeDefNew, capabilityTypeDefOld);
270     }
271
272     private Either<CapabilityTypeDefinition, StorageOperationStatus> updateCapabilityTypeOnGraph(CapabilityTypeDefinition capabilityTypeDefinitionNew,
273                                                                                                  CapabilityTypeDefinition capabilityTypeDefinitionOld) {
274         return janusGraphGenericDao.updateNode(new CapabilityTypeData(capabilityTypeDefinitionNew), CapabilityTypeData.class).right()
275             .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus).left()
276             .bind(updatedNode -> updateProperties(capabilityTypeDefinitionNew.getUniqueId(), capabilityTypeDefinitionNew.getProperties())).left()
277             .bind(updatedProperties -> updateDerivedFrom(capabilityTypeDefinitionNew, capabilityTypeDefinitionOld.getDerivedFrom())).right()
278             .bind(result -> TypeOperations.mapOkStatus(result, null)).left().map(updatedDerivedFrom -> capabilityTypeDefinitionNew);
279     }
280
281     private Either<Map<String, PropertyData>, StorageOperationStatus> updateProperties(String capabilityTypeId,
282                                                                                        Map<String, PropertyDefinition> properties) {
283         log.debug("#updateCapabilityTypeProperties - updating properties for capability type with id {}", capabilityTypeId);
284         return propertyOperation.mergePropertiesAssociatedToNode(NodeTypeEnum.CapabilityType, capabilityTypeId, properties).right()
285             .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
286     }
287
288     private Either<GraphRelation, StorageOperationStatus> updateDerivedFrom(CapabilityTypeDefinition updatedCapabilityType,
289                                                                             String currDerivedFromCapabilityType) {
290         if (StringUtils.equals(updatedCapabilityType.getDerivedFrom(), currDerivedFromCapabilityType)) {
291             return Either.right(StorageOperationStatus.OK);
292         }
293         StorageOperationStatus status = isLegalToReplaceParent(currDerivedFromCapabilityType, updatedCapabilityType.getDerivedFrom(),
294             updatedCapabilityType.getType());
295         if (status != StorageOperationStatus.OK) {
296             return Either.right(status);
297         }
298         String capabilityTypeId = updatedCapabilityType.getUniqueId();
299         log.debug(
300             "#updateCapabilityTypeDerivedFrom - updating capability type derived from relation for capability type with id {}. old derived type {}. new derived type {}",
301             capabilityTypeId, currDerivedFromCapabilityType, updatedCapabilityType.getDerivedFrom());
302         StorageOperationStatus deleteDerivedRelationStatus = deleteDerivedFromCapabilityType(capabilityTypeId, currDerivedFromCapabilityType);
303         if (deleteDerivedRelationStatus != StorageOperationStatus.OK) {
304             return Either.right(deleteDerivedRelationStatus);
305         }
306         return addDerivedFromRelation(updatedCapabilityType, capabilityTypeId);
307     }
308
309     private StorageOperationStatus isLegalToReplaceParent(String oldTypeParent, String newTypeParent, String childType) {
310         return derivedFromOperation
311             .isUpdateParentAllowed(oldTypeParent, newTypeParent, childType, NodeTypeEnum.CapabilityType, CapabilityTypeData.class,
312                 t -> t.getCapabilityTypeDataDefinition().getType());
313     }
314
315     private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(CapabilityTypeDefinition capabilityTypeDef, String ptUniqueId) {
316         String derivedFrom = capabilityTypeDef.getDerivedFrom();
317         if (derivedFrom == null) {
318             return Either.left(null);
319         }
320         log.debug("#addDerivedFromRelationBefore - adding derived from relation between capability type {} to its parent {}",
321             capabilityTypeDef.getType(), derivedFrom);
322         return this.getCapabilityType(derivedFrom, true).left().bind(derivedFromCapabilityType -> derivedFromOperation
323             .addDerivedFromRelation(ptUniqueId, derivedFromCapabilityType.getUniqueId(), NodeTypeEnum.CapabilityType));
324     }
325
326     private StorageOperationStatus deleteDerivedFromCapabilityType(String capabilityTypeId, String derivedFromType) {
327         if (derivedFromType == null) {
328             return StorageOperationStatus.OK;
329         }
330         log.debug("#deleteDerivedFromCapabilityType - deleting derivedFrom relation for capability type with id {} and its derived type {}",
331             capabilityTypeId, derivedFromType);
332         return getCapabilityType(derivedFromType, true).either(derivedFromNode -> derivedFromOperation
333             .removeDerivedFromRelation(capabilityTypeId, derivedFromNode.getUniqueId(), NodeTypeEnum.CapabilityType), err -> err);
334     }
335
336     private void updateCapabilityTypeData(CapabilityTypeDefinition updatedTypeDefinition, CapabilityTypeDefinition currTypeDefinition) {
337         updatedTypeDefinition.setUniqueId(currTypeDefinition.getUniqueId());
338         updatedTypeDefinition.setCreationTime(currTypeDefinition.getCreationTime());
339     }
340
341     /**
342      * FOR TEST ONLY
343      *
344      * @param propertyOperation
345      */
346     public void setPropertyOperation(PropertyOperation propertyOperation) {
347         this.propertyOperation = propertyOperation;
348     }
349
350     @Override
351     public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition) {
352         return addCapabilityType(capabilityTypeDefinition, true);
353     }
354
355     @Override
356     public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId) {
357         return getCapabilityType(uniqueId, true);
358     }
359
360     public Either<Map<String, CapabilityTypeDefinition>, JanusGraphOperationStatus> getAllCapabilityTypes() {
361         Map<String, CapabilityTypeDefinition> capabilityTypes = new HashMap<>();
362         Either<Map<String, CapabilityTypeDefinition>, JanusGraphOperationStatus> result = Either.left(capabilityTypes);
363         Either<List<CapabilityTypeData>, JanusGraphOperationStatus> getAllCapabilityTypes = janusGraphGenericDao
364             .getByCriteria(NodeTypeEnum.CapabilityType, null, CapabilityTypeData.class);
365         if (getAllCapabilityTypes.isRight()) {
366             JanusGraphOperationStatus status = getAllCapabilityTypes.right().value();
367             if (status != JanusGraphOperationStatus.NOT_FOUND) {
368                 return Either.right(status);
369             } else {
370                 return result;
371             }
372         }
373         List<CapabilityTypeData> list = getAllCapabilityTypes.left().value();
374         if (list != null) {
375             log.trace("Number of data types to load is {}", list.size());
376             //Set properties
377             for (CapabilityTypeData capabilityTypeData : list) {
378                 log.trace("Going to fetch data type {}. uid is {}", capabilityTypeData.getCapabilityTypeDataDefinition().getType(),
379                     capabilityTypeData.getUniqueId());
380                 Either<CapabilityTypeDefinition, JanusGraphOperationStatus> capabilityTypesByUid = getAndAddPropertiesANdDerivedFrom(
381                     capabilityTypeData.getUniqueId(), capabilityTypes);
382                 if (capabilityTypesByUid.isRight()) {
383                     JanusGraphOperationStatus status = capabilityTypesByUid.right().value();
384                     if (status == JanusGraphOperationStatus.NOT_FOUND) {
385                         status = JanusGraphOperationStatus.INVALID_ID;
386                     }
387                     return Either.right(status);
388                 }
389             }
390         }
391         return result;
392     }
393
394     private void fillDerivedFrom(String uniqueId, CapabilityTypeDefinition capabilityType) {
395         log.debug("#fillDerivedFrom - fetching capability type {} derived node", capabilityType.getType());
396         derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.CapabilityType, CapabilityTypeData.class).right()
397             .bind(this::handleDerivedFromNotExist).left().map(derivedFrom -> setDerivedFrom(capabilityType, derivedFrom));
398     }
399
400     private Either<CapabilityTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
401         if (err == StorageOperationStatus.NOT_FOUND) {
402             return Either.left(null);
403         }
404         return Either.right(err);
405     }
406
407     private CapabilityTypeData setDerivedFrom(CapabilityTypeDefinition capabilityTypeDefinition, CapabilityTypeData derivedFrom) {
408         if (derivedFrom != null) {
409             capabilityTypeDefinition.setDerivedFrom(derivedFrom.getCapabilityTypeDataDefinition().getType());
410         }
411         return derivedFrom;
412     }
413
414     private Either<CapabilityTypeDefinition, JanusGraphOperationStatus> getAndAddPropertiesANdDerivedFrom(String uniqueId,
415                                                                                                           Map<String, CapabilityTypeDefinition> capabilityTypeDefinitionMap) {
416         if (capabilityTypeDefinitionMap.containsKey(uniqueId)) {
417             return Either.left(capabilityTypeDefinitionMap.get(uniqueId));
418         }
419         Either<CapabilityTypeData, JanusGraphOperationStatus> capabilityTypesRes = janusGraphGenericDao
420             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, CapabilityTypeData.class);
421         if (capabilityTypesRes.isRight()) {
422             JanusGraphOperationStatus status = capabilityTypesRes.right().value();
423             log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
424             return Either.right(status);
425         }
426         CapabilityTypeData ctData = capabilityTypesRes.left().value();
427         CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition());
428         Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesStatus = OperationUtils
429             .fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType);
430         if (propertiesStatus.isRight() && propertiesStatus.right().value() != JanusGraphOperationStatus.OK) {
431             log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
432             return Either.right(propertiesStatus.right().value());
433         }
434         if (propertiesStatus.isLeft()) {
435             capabilityTypeDefinition.setProperties(propertiesStatus.left().value());
436         }
437         fillDerivedFrom(uniqueId, capabilityTypeDefinition);
438         capabilityTypeDefinitionMap.put(capabilityTypeDefinition.getType(), capabilityTypeDefinition);
439         return Either.left(capabilityTypeDefinition);
440     }
441 }