diff options
Diffstat (limited to 'catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java')
-rw-r--r-- | catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java | 734 |
1 files changed, 378 insertions, 356 deletions
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java index 9b31c71787..97f3e80e2a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java @@ -20,379 +20,401 @@ package org.openecomp.sdc.be.model.operations.impl; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - +import fj.data.Either; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge; import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; -import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.dao.titan.TitanGenericDao; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.model.CapabilityTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.operations.api.ICapabilityOperation; +import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.api.TypeOperations; import org.openecomp.sdc.be.resources.data.CapabilityTypeData; import org.openecomp.sdc.be.resources.data.PropertyData; -import org.openecomp.sdc.be.resources.data.UniqueIdData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import fj.data.Either; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Component("capability-type-operation") public class CapabilityTypeOperation extends AbstractOperation implements ICapabilityTypeOperation { - @Autowired - private PropertyOperation propertyOperation; - @Autowired - private ICapabilityOperation capabilityOperation; - - public CapabilityTypeOperation() { - super(); - } - - private static Logger log = LoggerFactory.getLogger(CapabilityTypeOperation.class.getName()); - - /** - * FOR TEST ONLY - * - * @param titanGenericDao - */ - public void setTitanGenericDao(TitanGenericDao titanGenericDao) { - this.titanGenericDao = titanGenericDao; - } - - @Override - public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition, boolean inTransaction) { - - Either<CapabilityTypeDefinition, StorageOperationStatus> result = null; - - try { - Either<CapabilityTypeDefinition, TitanOperationStatus> validationRes = validateUpdateProperties(capabilityTypeDefinition); - if (validationRes.isRight()) { - log.error("One or all properties of capability type {} not valid. status is {}", capabilityTypeDefinition, validationRes.right().value().name()); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(validationRes.right().value())); - return result; - } - Either<CapabilityTypeData, TitanOperationStatus> eitherStatus = addCapabilityTypeToGraph(capabilityTypeDefinition); - - if (eitherStatus.isRight()) { - log.error("Failed to add capability {} to Graph. status is {}", capabilityTypeDefinition, eitherStatus.right().value().name()); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(eitherStatus.right().value())); - return result; - } else { - CapabilityTypeData capabilityTypeData = eitherStatus.left().value(); - - CapabilityTypeDefinition capabilityTypeDefResult = convertCTDataToCTDefinition(capabilityTypeData); - log.debug("The returned CapabilityTypeDefinition is {}", capabilityTypeDefResult); - result = Either.left(capabilityTypeDefResult); - return result; - } - } - - finally { - if (false == inTransaction) { - if (result == null || result.isRight()) { - log.error("Going to execute rollback on graph."); - titanGenericDao.rollback(); - } else { - log.debug("Going to execute commit on graph."); - titanGenericDao.commit(); - } - } - } - - } - - private Either<CapabilityTypeDefinition, TitanOperationStatus> validateUpdateProperties(CapabilityTypeDefinition capabilityTypeDefinition) { - TitanOperationStatus error = null; - if (capabilityTypeDefinition.getProperties() != null && !capabilityTypeDefinition.getProperties().isEmpty() && capabilityTypeDefinition.getDerivedFrom() != null) { - Either<Map<String, PropertyDefinition>, TitanOperationStatus> allPropertiesRes = capabilityOperation.getAllCapabilityTypePropertiesFromAllDerivedFrom(capabilityTypeDefinition.getDerivedFrom()); - if (allPropertiesRes.isRight() && !allPropertiesRes.right().value().equals(TitanOperationStatus.NOT_FOUND)) { - error = allPropertiesRes.right().value(); - log.debug("Couldn't fetch derived from property nodes for capability type {}, error: {}", capabilityTypeDefinition.getType(), error); - } - if (error == null && !allPropertiesRes.left().value().isEmpty()) { - Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value(); - capabilityTypeDefinition.getProperties().entrySet().stream().filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null) - .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType())); - - Either<List<PropertyDefinition>, TitanOperationStatus> validatePropertiesRes = capabilityOperation.validatePropertyUniqueness(allPropertiesRes.left().value(), - capabilityTypeDefinition.getProperties().values().stream().collect(Collectors.toList())); - if (validatePropertiesRes.isRight()) { - error = validatePropertiesRes.right().value(); - } - } - } - if (error == null) { - return Either.left(capabilityTypeDefinition); - } - return Either.right(error); - } - - /** - * - * convert between graph Node object to Java object - * - * @param capabilityTypeData - * @return - */ - protected CapabilityTypeDefinition convertCTDataToCTDefinition(CapabilityTypeData capabilityTypeData) { - log.debug("The object returned after create capability is {}", capabilityTypeData); - - CapabilityTypeDefinition capabilityTypeDefResult = new CapabilityTypeDefinition(capabilityTypeData.getCapabilityTypeDataDefinition()); - - return capabilityTypeDefResult; - } - - /** - * - * Add capability type to graph. - * - * 1. Add capability type node - * - * 2. Add edge between the former node to its parent(if exists) - * - * 3. Add property node and associate it to the node created at #1. (per property & if exists) - * - * @param capabilityTypeDefinition - * @return - */ - private Either<CapabilityTypeData, TitanOperationStatus> addCapabilityTypeToGraph(CapabilityTypeDefinition capabilityTypeDefinition) { - - log.debug("Got capability type {}", capabilityTypeDefinition); - - String ctUniqueId = UniqueIdBuilder.buildCapabilityTypeUid(capabilityTypeDefinition.getType()); - // capabilityTypeDefinition.setUniqueId(ctUniqueId); - - CapabilityTypeData capabilityTypeData = buildCapabilityTypeData(capabilityTypeDefinition, ctUniqueId); - - log.debug("Before adding capability type to graph. capabilityTypeData = {}", capabilityTypeData); - Either<CapabilityTypeData, TitanOperationStatus> createCTResult = titanGenericDao.createNode(capabilityTypeData, CapabilityTypeData.class); - log.debug("After adding capability type to graph. status is = {}", createCTResult); - - if (createCTResult.isRight()) { - TitanOperationStatus operationStatus = createCTResult.right().value(); - log.error("Failed to capability type {} to graph. status is {}", capabilityTypeDefinition.getType(), operationStatus); - return Either.right(operationStatus); - } - - CapabilityTypeData resultCTD = createCTResult.left().value(); - Map<String, PropertyDefinition> propertiesMap = capabilityTypeDefinition.getProperties(); - Collection<PropertyDefinition> properties = propertiesMap != null ? propertiesMap.values() : null; - Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToCapablityType = propertyOperation.addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.CapabilityType, propertiesMap); - if (addPropertiesToCapablityType.isRight()) { - log.error("Failed add properties {} to capability {}", propertiesMap, capabilityTypeDefinition.getType()); - return Either.right(addPropertiesToCapablityType.right().value()); - } - - String derivedFrom = capabilityTypeDefinition.getDerivedFrom(); - if (derivedFrom != null) { - log.debug("Before creating relation between capability type {} to its parent {}", ctUniqueId, derivedFrom); - UniqueIdData from = new UniqueIdData(NodeTypeEnum.CapabilityType, ctUniqueId); - UniqueIdData to = new UniqueIdData(NodeTypeEnum.CapabilityType, derivedFrom); - Either<GraphRelation, TitanOperationStatus> createRelation = titanGenericDao.createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null); - log.debug("After create relation between capability type {} to its parent {}. status is {}", ctUniqueId, derivedFrom, createRelation); - if (createRelation.isRight()) { - return Either.right(createRelation.right().value()); - } - } - - return Either.left(createCTResult.left().value()); - - } - - private CapabilityTypeData buildCapabilityTypeData(CapabilityTypeDefinition capabilityTypeDefinition, String ctUniqueId) { - - CapabilityTypeData capabilityTypeData = new CapabilityTypeData(capabilityTypeDefinition); - - capabilityTypeData.getCapabilityTypeDataDefinition().setUniqueId(ctUniqueId); - Long creationDate = capabilityTypeData.getCapabilityTypeDataDefinition().getCreationTime(); - if (creationDate == null) { - creationDate = System.currentTimeMillis(); - } - capabilityTypeData.getCapabilityTypeDataDefinition().setCreationTime(creationDate); - capabilityTypeData.getCapabilityTypeDataDefinition().setModificationTime(creationDate); - return capabilityTypeData; - } - - @Override - public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId, boolean inTransaction) { - - Either<CapabilityTypeDefinition, StorageOperationStatus> result = null; - try { - - Either<CapabilityTypeDefinition, TitanOperationStatus> ctResult = this.getCapabilityTypeByUid(uniqueId); - - if (ctResult.isRight()) { - TitanOperationStatus status = ctResult.right().value(); - if (status != TitanOperationStatus.NOT_FOUND) { - log.error("Failed to retrieve information on capability type {}. status is {}", uniqueId, status); - } - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value())); - return result; - } - - result = Either.left(ctResult.left().value()); - - return result; - } finally { - if (false == inTransaction) { - log.debug("Going to execute commit on graph."); - titanGenericDao.commit(); - } - } - } - - - public Either<CapabilityTypeData, TitanOperationStatus> getCapabilityTypeByType(String capabilityType) { - Either<CapabilityTypeData, TitanOperationStatus> capabilityTypesRes = titanGenericDao.getNode(GraphPropertiesDictionary.TYPE.getProperty(), capabilityType, CapabilityTypeData.class); - - if (capabilityTypesRes.isRight()) { - TitanOperationStatus status = capabilityTypesRes.right().value(); - log.debug("Capability type {} cannot be found in graph. status is {}", capabilityType, status); - - return Either.right(status); - } - - CapabilityTypeData ctData = capabilityTypesRes.left().value(); - return Either.left(ctData); - } - - /** - * Build Capability type object from graph by unique id - * - * @param uniqueId - * @return - */ - public Either<CapabilityTypeDefinition, TitanOperationStatus> getCapabilityTypeByUid(String uniqueId) { - - Either<CapabilityTypeDefinition, TitanOperationStatus> result = null; - - Either<CapabilityTypeData, TitanOperationStatus> capabilityTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, CapabilityTypeData.class); - - if (capabilityTypesRes.isRight()) { - TitanOperationStatus status = capabilityTypesRes.right().value(); - log.debug("Capability type {} cannot be found in graph. status is {}", uniqueId, status); - return Either.right(status); - } - - CapabilityTypeData ctData = capabilityTypesRes.left().value(); - CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition()); - - TitanOperationStatus propertiesStatus = fillProperties(uniqueId, capabilityTypeDefinition); - if (propertiesStatus != TitanOperationStatus.OK) { - log.error("Failed to fetch properties of capability type {}", uniqueId); - return Either.right(propertiesStatus); - } - - Either<ImmutablePair<CapabilityTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, GraphEdgeLabels.DERIVED_FROM, - NodeTypeEnum.CapabilityType, CapabilityTypeData.class); - log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode); - if (parentNode.isRight()) { - TitanOperationStatus titanOperationStatus = parentNode.right().value(); - if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) { - log.error("Failed to find the parent capability of capability type {}. status is {}", uniqueId, titanOperationStatus); - result = Either.right(titanOperationStatus); - return result; - } - } else { - // derived from node was found - ImmutablePair<CapabilityTypeData, GraphEdge> immutablePair = parentNode.left().value(); - CapabilityTypeData parentCT = immutablePair.getKey(); - capabilityTypeDefinition.setDerivedFrom(parentCT.getCapabilityTypeDataDefinition().getType()); - } - result = Either.left(capabilityTypeDefinition); - - return result; - } - - private TitanOperationStatus fillProperties(String uniqueId, CapabilityTypeDefinition capabilityTypeDefinition) { - - Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode = propertyOperation.findPropertiesOfNode(NodeTypeEnum.CapabilityType, uniqueId); - if (findPropertiesOfNode.isRight()) { - TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value(); - log.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus); - if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) { - return TitanOperationStatus.OK; - } else { - return titanOperationStatus; - } - } else { - Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value(); - capabilityTypeDefinition.setProperties(properties); - return TitanOperationStatus.OK; - } - } - - public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) { - Map<String, Object> propertiesToMatch = new HashMap<String, Object>(); - propertiesToMatch.put(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childCandidateType); - Either<List<CapabilityTypeData>, TitanOperationStatus> getResponse = titanGenericDao.getByCriteria(NodeTypeEnum.CapabilityType, propertiesToMatch, CapabilityTypeData.class); - if (getResponse.isRight()) { - TitanOperationStatus titanOperationStatus = getResponse.right().value(); - log.debug("Couldn't fetch capability type {}, error: {}", childCandidateType, titanOperationStatus); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus)); - } - String childUniqueId = getResponse.left().value().get(0).getUniqueId(); - Set<String> travelledTypes = new HashSet<>(); - do { - travelledTypes.add(childUniqueId); - Either<List<ImmutablePair<CapabilityTypeData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childUniqueId, GraphEdgeLabels.DERIVED_FROM, - NodeTypeEnum.CapabilityType, CapabilityTypeData.class); - if (childrenNodes.isRight()) { - if (childrenNodes.right().value() != TitanOperationStatus.NOT_FOUND) { - TitanOperationStatus titanOperationStatus = getResponse.right().value(); - log.debug("Couldn't fetch derived from node for capability type {}, error: {}", childCandidateType, titanOperationStatus); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus)); - } else { - log.debug("Derived from node is not found for type {} - this is OK for root capability."); - return Either.left(false); - } - } - String derivedFromUniqueId = childrenNodes.left().value().get(0).getLeft().getUniqueId(); - if (derivedFromUniqueId.equals(parentCandidateType)) { - log.debug("Verified that capability type {} derives from capability type {}", childCandidateType, parentCandidateType); - return Either.left(true); - } - childUniqueId = derivedFromUniqueId; - } while (!travelledTypes.contains(childUniqueId)); - // this stop condition should never be used, if we use it, we have an - // illegal cycle in graph - "derived from" hierarchy cannot be cycled. - // It's here just to avoid infinite loop in case we have such cycle. - log.error("Detected a cycle of \"derived from\" edges starting at capability type node {}", childUniqueId); - return Either.right(StorageOperationStatus.GENERAL_ERROR); - } - - /** - * FOR TEST ONLY - * - * @param propertyOperation - */ - public void setPropertyOperation(PropertyOperation propertyOperation) { - this.propertyOperation = propertyOperation; - } - - @Override - public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition) { - - return addCapabilityType(capabilityTypeDefinition, false); - } - - @Override - public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId) { - return getCapabilityType(uniqueId, false); - } - + @Autowired + private PropertyOperation propertyOperation; + @Autowired + private DerivedFromOperation derivedFromOperation; + + public CapabilityTypeOperation() { + super(); + } + + private static final Logger log = Logger.getLogger(CapabilityTypeOperation.class.getName()); + + /** + * FOR TEST ONLY + * + * @param titanGenericDao + */ + public void setTitanGenericDao(TitanGenericDao titanGenericDao) { + this.titanGenericDao = titanGenericDao; + } + + @Override + public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition, boolean inTransaction) { + + Either<CapabilityTypeDefinition, StorageOperationStatus> result = null; + + try { + Either<CapabilityTypeDefinition, StorageOperationStatus> validationRes = validateUpdateProperties(capabilityTypeDefinition); + if (validationRes.isRight()) { + log.error("#addCapabilityType - One or all properties of capability type {} not valid. status is {}", capabilityTypeDefinition, validationRes.right().value()); + return result; + } + + Either<CapabilityTypeData, StorageOperationStatus> eitherStatus = addCapabilityTypeToGraph(capabilityTypeDefinition); + + result = eitherStatus.left() + .map(CapabilityTypeData::getUniqueId) + .left() + .bind(uniqueId -> getCapabilityType(uniqueId, inTransaction)); + + if(result.isLeft()) { + log.debug("#addCapabilityType - The returned CapabilityTypeDefinition is {}", result.left().value()); + } + + return result; + } + + finally { + if (!inTransaction) { + if (result == null || result.isRight()) { + log.error("#addCapabilityType - Going to execute rollback on graph."); + titanGenericDao.rollback(); + } else { + log.debug("#addCapabilityType - Going to execute commit on graph."); + titanGenericDao.commit(); + } + } + } + + } + + public Either<Map<String, PropertyDefinition>, TitanOperationStatus> getAllCapabilityTypePropertiesFromAllDerivedFrom(String firstParentType) { + return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.CapabilityType, CapabilityTypeData.class); + } + + public Either<CapabilityTypeDefinition, StorageOperationStatus> validateUpdateProperties(CapabilityTypeDefinition capabilityTypeDefinition) { + TitanOperationStatus error = null; + if (MapUtils.isNotEmpty(capabilityTypeDefinition.getProperties()) && capabilityTypeDefinition.getDerivedFrom() != null) { + Either<Map<String, PropertyDefinition>, TitanOperationStatus> allPropertiesRes = + getAllCapabilityTypePropertiesFromAllDerivedFrom(capabilityTypeDefinition.getDerivedFrom()); + if (allPropertiesRes.isRight() && !allPropertiesRes.right().value().equals(TitanOperationStatus.NOT_FOUND)) { + error = allPropertiesRes.right().value(); + log.debug("Couldn't fetch derived from property nodes for capability type {}, error: {}", capabilityTypeDefinition.getType(), error); + } + if (error == null && !allPropertiesRes.left().value().isEmpty()) { + Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value(); + capabilityTypeDefinition.getProperties().entrySet().stream().filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null) + .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType())); + + List<PropertyDefinition> properties = capabilityTypeDefinition.getProperties().values().stream().collect(Collectors.toList()); + Either<List<PropertyDefinition>, TitanOperationStatus> validatePropertiesRes = propertyOperation.validatePropertiesUniqueness(allPropertiesRes.left().value(), + properties); + if (validatePropertiesRes.isRight()) { + error = validatePropertiesRes.right().value(); + } + } + } + if (error == null) { + return Either.left(capabilityTypeDefinition); + } + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error)); + } + + + /** + * + * convert between graph Node object to Java object + * + * @param capabilityTypeData + * @return + */ + protected CapabilityTypeDefinition convertCTDataToCTDefinition(CapabilityTypeData capabilityTypeData) { + log.debug("The object returned after create capability is {}", capabilityTypeData); + + return new CapabilityTypeDefinition(capabilityTypeData.getCapabilityTypeDataDefinition()); + } + + /** + * + * Add capability type to graph. + * + * 1. Add capability type node + * + * 2. Add edge between the former node to its parent(if exists) + * + * 3. Add property node and associate it to the node created at #1. (per property & if exists) + * + * @param capabilityTypeDefinition + * @return + */ + private Either<CapabilityTypeData, StorageOperationStatus> addCapabilityTypeToGraph(CapabilityTypeDefinition capabilityTypeDefinition) { + + log.debug("Got capability type {}", capabilityTypeDefinition); + + String ctUniqueId = UniqueIdBuilder.buildCapabilityTypeUid(capabilityTypeDefinition.getType()); + CapabilityTypeData capabilityTypeData = buildCapabilityTypeData(capabilityTypeDefinition, ctUniqueId); + + log.debug("Before adding capability type to graph. capabilityTypeData = {}", capabilityTypeData); + Either<CapabilityTypeData, TitanOperationStatus> createCTResult = titanGenericDao.createNode(capabilityTypeData, CapabilityTypeData.class); + log.debug("After adding capability type to graph. status is = {}", createCTResult); + + if (createCTResult.isRight()) { + TitanOperationStatus operationStatus = createCTResult.right().value(); + log.error("Failed to capability type {} to graph. status is {}", capabilityTypeDefinition.getType(), operationStatus); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(operationStatus)); + } + + CapabilityTypeData resultCTD = createCTResult.left().value(); + Map<String, PropertyDefinition> propertiesMap = capabilityTypeDefinition.getProperties(); + Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToCapablityType = propertyOperation.addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.CapabilityType, propertiesMap); + if (addPropertiesToCapablityType.isRight()) { + log.error("Failed add properties {} to capability {}", propertiesMap, capabilityTypeDefinition.getType()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(addPropertiesToCapablityType.right().value())); + } + + return addDerivedFromRelation(capabilityTypeDefinition, ctUniqueId) + .left() + .map(updatedDerivedFrom -> createCTResult.left().value()); + + + } + + private CapabilityTypeData buildCapabilityTypeData(CapabilityTypeDefinition capabilityTypeDefinition, String ctUniqueId) { + + CapabilityTypeData capabilityTypeData = new CapabilityTypeData(capabilityTypeDefinition); + + capabilityTypeData.getCapabilityTypeDataDefinition().setUniqueId(ctUniqueId); + Long creationDate = capabilityTypeData.getCapabilityTypeDataDefinition().getCreationTime(); + if (creationDate == null) { + creationDate = System.currentTimeMillis(); + } + capabilityTypeData.getCapabilityTypeDataDefinition().setCreationTime(creationDate); + capabilityTypeData.getCapabilityTypeDataDefinition().setModificationTime(creationDate); + return capabilityTypeData; + } + + @Override + public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId, boolean inTransaction) { + + Either<CapabilityTypeDefinition, StorageOperationStatus> result = null; + try { + + Either<CapabilityTypeDefinition, TitanOperationStatus> ctResult = this.getCapabilityTypeByUid(uniqueId); + + if (ctResult.isRight()) { + TitanOperationStatus status = ctResult.right().value(); + if (status != TitanOperationStatus.NOT_FOUND) { + log.error("Failed to retrieve information on capability type {}. status is {}", uniqueId, status); + } + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value())); + return result; + } + + result = Either.left(ctResult.left().value()); + + return result; + } finally { + if (!inTransaction) { + log.debug("Going to execute commit on graph."); + titanGenericDao.commit(); + } + } + } + + + public Either<CapabilityTypeDefinition, TitanOperationStatus> getCapabilityTypeByType(String capabilityType) { + // Optimization: In case of Capability Type its unique ID is the same as type + return getCapabilityTypeByUid(capabilityType); + } + + /** + * Build Capability type object from graph by unique id + * + * @param uniqueId + * @return + */ + public Either<CapabilityTypeDefinition, TitanOperationStatus> getCapabilityTypeByUid(String uniqueId) { + + Either<CapabilityTypeDefinition, TitanOperationStatus> result = null; + + Either<CapabilityTypeData, TitanOperationStatus> capabilityTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, CapabilityTypeData.class); + + if (capabilityTypesRes.isRight()) { + TitanOperationStatus status = capabilityTypesRes.right().value(); + log.debug("Capability type {} cannot be found in graph. status is {}", uniqueId, status); + return Either.right(status); + } + + CapabilityTypeData ctData = capabilityTypesRes.left().value(); + CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition()); + + TitanOperationStatus propertiesStatus = fillProperties(uniqueId, capabilityTypeDefinition); + if (propertiesStatus != TitanOperationStatus.OK) { + log.error("Failed to fetch properties of capability type {}", uniqueId); + return Either.right(propertiesStatus); + } + + Either<ImmutablePair<CapabilityTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, GraphEdgeLabels.DERIVED_FROM, + NodeTypeEnum.CapabilityType, CapabilityTypeData.class); + log.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode); + if (parentNode.isRight()) { + TitanOperationStatus titanOperationStatus = parentNode.right().value(); + if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) { + log.error("Failed to find the parent capability of capability type {}. status is {}", uniqueId, titanOperationStatus); + result = Either.right(titanOperationStatus); + return result; + } + } else { + // derived from node was found + ImmutablePair<CapabilityTypeData, GraphEdge> immutablePair = parentNode.left().value(); + CapabilityTypeData parentCT = immutablePair.getKey(); + capabilityTypeDefinition.setDerivedFrom(parentCT.getCapabilityTypeDataDefinition().getType()); + } + result = Either.left(capabilityTypeDefinition); + + return result; + } + + private TitanOperationStatus fillProperties(String uniqueId, CapabilityTypeDefinition capabilityTypeDefinition) { + + Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode = propertyOperation.findPropertiesOfNode(NodeTypeEnum.CapabilityType, uniqueId); + if (findPropertiesOfNode.isRight()) { + TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value(); + log.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus); + if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) { + return TitanOperationStatus.OK; + } else { + return titanOperationStatus; + } + } else { + Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value(); + capabilityTypeDefinition.setProperties(properties); + return TitanOperationStatus.OK; + } + } + + public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) { + return derivedFromOperation.isTypeDerivedFrom(childCandidateType, parentCandidateType, null, NodeTypeEnum.CapabilityType, CapabilityTypeData.class, t -> t.getCapabilityTypeDataDefinition().getType()); + } + + + @Override + public Either<CapabilityTypeDefinition, StorageOperationStatus> updateCapabilityType(CapabilityTypeDefinition capabilityTypeDefNew, + CapabilityTypeDefinition capabilityTypeDefOld) { + log.debug("updating capability type {}", capabilityTypeDefNew.getType()); + updateCapabilityTypeData(capabilityTypeDefNew, capabilityTypeDefOld); + return updateCapabilityTypeOnGraph(capabilityTypeDefNew, capabilityTypeDefOld); + } + + + private Either<CapabilityTypeDefinition, StorageOperationStatus> updateCapabilityTypeOnGraph(CapabilityTypeDefinition capabilityTypeDefinitionNew, CapabilityTypeDefinition capabilityTypeDefinitionOld) { + return titanGenericDao.updateNode(new CapabilityTypeData(capabilityTypeDefinitionNew), CapabilityTypeData.class) + .right() + .map(DaoStatusConverter::convertTitanStatusToStorageStatus) + .left() + .bind(updatedNode -> updateProperties(capabilityTypeDefinitionNew.getUniqueId(), capabilityTypeDefinitionNew.getProperties())) + .left() + .bind(updatedProperties -> updateDerivedFrom(capabilityTypeDefinitionNew, capabilityTypeDefinitionOld.getDerivedFrom())) + .right() + .bind(result -> TypeOperations.mapOkStatus(result, null)) + .left() + .map(updatedDerivedFrom -> capabilityTypeDefinitionNew); + } + + private Either<Map<String, PropertyData>, StorageOperationStatus> updateProperties(String capabilityTypeId, Map<String, PropertyDefinition> properties) { + log.debug("#updateCapabilityTypeProperties - updating properties for capability type with id {}", capabilityTypeId); + return propertyOperation.mergePropertiesAssociatedToNode(NodeTypeEnum.CapabilityType, capabilityTypeId, properties) + .right() + .map(DaoStatusConverter::convertTitanStatusToStorageStatus); + } + + private Either<GraphRelation, StorageOperationStatus> updateDerivedFrom(CapabilityTypeDefinition updatedCapabilityType, String currDerivedFromCapabilityType) { + if( StringUtils.equals(updatedCapabilityType.getDerivedFrom(), currDerivedFromCapabilityType)) { + return Either.right(StorageOperationStatus.OK); + } + + StorageOperationStatus status = isLegalToReplaceParent(currDerivedFromCapabilityType, updatedCapabilityType.getDerivedFrom(), updatedCapabilityType.getType()); + if ( status != StorageOperationStatus.OK) { + return Either.right(status); + } + + String capabilityTypeId = updatedCapabilityType.getUniqueId(); + log.debug("#updateCapabilityTypeDerivedFrom - updating capability type derived from relation for capability type with id {}. old derived type {}. new derived type {}", capabilityTypeId, currDerivedFromCapabilityType, updatedCapabilityType.getDerivedFrom()); + StorageOperationStatus deleteDerivedRelationStatus = deleteDerivedFromCapabilityType(capabilityTypeId, currDerivedFromCapabilityType); + if (deleteDerivedRelationStatus != StorageOperationStatus.OK) { + return Either.right(deleteDerivedRelationStatus); + } + return addDerivedFromRelation(updatedCapabilityType, capabilityTypeId); + } + + private StorageOperationStatus isLegalToReplaceParent(String oldTypeParent, String newTypeParent, String childType) { + return derivedFromOperation.isUpdateParentAllowed(oldTypeParent, newTypeParent, childType, NodeTypeEnum.CapabilityType, CapabilityTypeData.class, t -> t.getCapabilityTypeDataDefinition().getType()); + } + + private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(CapabilityTypeDefinition capabilityTypeDef, String ptUniqueId) { + String derivedFrom = capabilityTypeDef.getDerivedFrom(); + if (derivedFrom == null) { + return Either.left(null); + } + log.debug("#addDerivedFromRelationBefore - adding derived from relation between capability type {} to its parent {}", capabilityTypeDef.getType(), derivedFrom); + return this.getCapabilityType(derivedFrom, true) + .left() + .bind(derivedFromCapabilityType -> derivedFromOperation.addDerivedFromRelation(ptUniqueId, derivedFromCapabilityType.getUniqueId(), NodeTypeEnum.CapabilityType)); + } + + private StorageOperationStatus deleteDerivedFromCapabilityType(String capabilityTypeId, String derivedFromType) { + if (derivedFromType == null) { + return StorageOperationStatus.OK; + } + log.debug("#deleteDerivedFromCapabilityType - deleting derivedFrom relation for capability type with id {} and its derived type {}", capabilityTypeId, derivedFromType); + return getCapabilityType(derivedFromType, true) + .either(derivedFromNode -> derivedFromOperation.removeDerivedFromRelation(capabilityTypeId, derivedFromNode.getUniqueId(), NodeTypeEnum.CapabilityType), + err -> err); + } + + private void updateCapabilityTypeData(CapabilityTypeDefinition updatedTypeDefinition, CapabilityTypeDefinition currTypeDefinition) { + updatedTypeDefinition.setUniqueId(currTypeDefinition.getUniqueId()); + updatedTypeDefinition.setCreationTime(currTypeDefinition.getCreationTime()); + } + + + /** + * FOR TEST ONLY + * + * @param propertyOperation + */ + public void setPropertyOperation(PropertyOperation propertyOperation) { + this.propertyOperation = propertyOperation; + } + + @Override + public Either<CapabilityTypeDefinition, StorageOperationStatus> addCapabilityType(CapabilityTypeDefinition capabilityTypeDefinition) { + + return addCapabilityType(capabilityTypeDefinition, true); + } + + @Override + public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId) { + return getCapabilityType(uniqueId, true); + } } |