summaryrefslogtreecommitdiffstats
path: root/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java')
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java1067
1 files changed, 1067 insertions, 0 deletions
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java
new file mode 100644
index 0000000000..2a8192421b
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ProductOperation.java
@@ -0,0 +1,1067 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.operations.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.Set;
+
+import com.thinkaurelius.titan.core.TitanTransaction;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+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.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.category.CategoryDataDefinition;
+import org.openecomp.sdc.be.datatypes.category.GroupingDataDefinition;
+import org.openecomp.sdc.be.datatypes.category.SubCategoryDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ProductMetadataDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
+import org.openecomp.sdc.be.model.category.GroupingDefinition;
+import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
+import org.openecomp.sdc.be.model.operations.api.IProductOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
+import org.openecomp.sdc.be.resources.data.ProductMetadataData;
+import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
+import org.openecomp.sdc.be.resources.data.UserData;
+import org.openecomp.sdc.be.resources.data.category.CategoryData;
+import org.openecomp.sdc.be.resources.data.category.GroupingData;
+import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
+import org.openecomp.sdc.common.util.ValidationUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+import fj.data.Either;
+
+@org.springframework.stereotype.Component("product-operation")
+public class ProductOperation extends ComponentOperation implements IProductOperation {
+
+ private static Logger log = LoggerFactory.getLogger(ProductOperation.class.getName());
+
+ public ProductOperation() {
+ log.debug("ProductOperation created");
+ }
+
+ @Override
+ protected ComponentMetadataData getMetaDataFromComponent(Component component) {
+ return getProductMetadataDataFromProduct((Product) component);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> Either<T, StorageOperationStatus> getComponent(String id, boolean inTransaction) {
+ return (Either<T, StorageOperationStatus>) getProduct(id, inTransaction);
+ }
+
+ // public <T> Either<T, StorageOperationStatus> getComponent_tx(String id,
+ // boolean inTransaction) {
+ // return (Either<T, StorageOperationStatus>) getProduct_tx(id,
+ // inTransaction);
+ // }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> Either<T, StorageOperationStatus> getComponentByNameAndVersion(String name, String version,
+ Map<String, Object> additionalParams, boolean inTransaction) {
+ return (Either<T, StorageOperationStatus>) getByNamesAndVersion(GraphPropertiesDictionary.NAME.getProperty(),
+ name, version, additionalParams, inTransaction);
+ }
+
+ @Override
+ public <T> Either<T, StorageOperationStatus> getLightComponent(String id, boolean inTransaction) {
+ return getLightComponent(id, NodeTypeEnum.Product, inTransaction);
+ }
+
+ @Override
+ public <T> Either<List<T>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters,
+ boolean inTransaction) {
+ return getFilteredComponents(filters, inTransaction, NodeTypeEnum.Product);
+ }
+
+ private Product convertProductDataToProduct(ProductMetadataData productData) {
+ ProductMetadataDefinition productMetadataDefinition = new ProductMetadataDefinition(
+ (ProductMetadataDataDefinition) productData.getMetadataDataDefinition());
+
+ Product product = new Product(productMetadataDefinition);
+
+ return product;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> Either<T, StorageOperationStatus> updateComponent(T component, boolean inTransaction) {
+ return (Either<T, StorageOperationStatus>) updateComponent((Component) component, inTransaction,
+ titanGenericDao, Product.class, NodeTypeEnum.Product);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Either<Component, StorageOperationStatus> deleteComponent(String id, boolean inTransaction) {
+ return (Either<Component, StorageOperationStatus>) (Either<?, StorageOperationStatus>) deleteProduct(id,
+ inTransaction);
+ }
+
+ @Override
+ public Either<List<ArtifactDefinition>, StorageOperationStatus> getAdditionalArtifacts(String resourceId,
+ boolean recursively, boolean inTransaction) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends org.openecomp.sdc.be.model.Component> Either<T, StorageOperationStatus> getComponent(String id,
+ Class<T> clazz) {
+ return (Either<T, StorageOperationStatus>) getProduct(id, false);
+ }
+
+ @Override
+ /**
+ * Deletes the product node
+ */
+ public Either<Product, StorageOperationStatus> deleteProduct(String productId, boolean inTransaction) {
+
+ Either<Product, StorageOperationStatus> result = Either.right(StorageOperationStatus.GENERAL_ERROR);
+
+ try {
+
+ Either<TitanGraph, TitanOperationStatus> graphResult = titanGenericDao.getGraph();
+ if (graphResult.isRight()) {
+ result = Either
+ .right(DaoStatusConverter.convertTitanStatusToStorageStatus(graphResult.right().value()));
+ return result;
+ }
+
+ Either<ProductMetadataData, TitanOperationStatus> productNode = titanGenericDao.getNode(
+ UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Product), productId, ProductMetadataData.class);
+ if (productNode.isRight()) {
+ TitanOperationStatus status = productNode.right().value();
+ log.error("Failed to find product {}. Status is {}", productId, status);
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+
+ Either<Product, StorageOperationStatus> productRes = getProduct(productId, true);
+ if (productRes.isRight()) {
+ StorageOperationStatus status = productRes.right().value();
+ log.error("Failed to find product {}", productId, status);
+ result = Either.right(status);
+ return result;
+ }
+ Product product = productRes.left().value();
+
+ Either<List<ComponentInstance>, StorageOperationStatus> deleteAllInstancesRes = componentInstanceOperation
+ .deleteAllComponentInstances(productId, NodeTypeEnum.Product, true);
+ log.debug("After deleting instances under product {}. Result is {}", productId, deleteAllInstancesRes);
+ if (deleteAllInstancesRes.isRight()) {
+ StorageOperationStatus status = deleteAllInstancesRes.right().value();
+ if (status != StorageOperationStatus.NOT_FOUND) {
+ log.error("Failed to delete instances under product {}. Status is {}", productId, status);
+ result = Either.right(status);
+ return result;
+ }
+ }
+
+ Either<ProductMetadataData, TitanOperationStatus> deleteProductNodeRes = titanGenericDao
+ .deleteNode(productNode.left().value(), ProductMetadataData.class);
+ if (deleteProductNodeRes.isRight()) {
+ TitanOperationStatus status = deleteProductNodeRes.right().value();
+ log.error("Failed to delete product node {}. Status is {}", productId, status);
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+
+ result = Either.left(product);
+
+ return result;
+
+ } finally {
+ if (false == inTransaction) {
+ if (result == null || result.isRight()) {
+ log.error("deleteProduct operation : Going to execute rollback on graph.");
+ titanGenericDao.rollback();
+ } else {
+ log.debug("deleteProduct operation : Going to execute commit on graph.");
+ titanGenericDao.commit();
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public Either<List<Product>, StorageOperationStatus> getProductCatalogData(boolean inTransaction) {
+
+ long start = System.currentTimeMillis();
+ try {
+ /*
+ * Map<String, Object> propertiesToMatch = new HashMap<>();
+ *
+ * propertiesToMatch.put(GraphPropertiesDictionary.STATE.getProperty
+ * (), LifecycleStateEnum.CERTIFIED.name());
+ * Either<List<ProductMetadataData>, TitanOperationStatus>
+ * lastVersionNodes = getLastVersion(NodeTypeEnum.Product,
+ * propertiesToMatch, ProductMetadataData.class); if
+ * (lastVersionNodes.isRight() && lastVersionNodes.right().value()
+ * != TitanOperationStatus.NOT_FOUND) { return
+ * Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus
+ * (lastVersionNodes.right().value())); } List<ProductMetadataData>
+ * notCertifiedHighest = (lastVersionNodes.isLeft() ?
+ * lastVersionNodes.left().value() : new
+ * ArrayList<ProductMetadataData>());
+ *
+ * propertiesToMatch.put(GraphPropertiesDictionary.
+ * IS_HIGHEST_VERSION.getProperty(), true);
+ * Either<List<ProductMetadataData>, TitanOperationStatus>
+ * componentsNodes =
+ * titanGenericDao.getByCriteria(NodeTypeEnum.Product,
+ * propertiesToMatch, ProductMetadataData.class); if
+ * (componentsNodes.isRight() && componentsNodes.right().value() !=
+ * TitanOperationStatus.NOT_FOUND) { return
+ * Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus
+ * (componentsNodes.right().value())); } List<ProductMetadataData>
+ * certifiedHighest = (componentsNodes.isLeft() ?
+ * componentsNodes.left().value() : new
+ * ArrayList<ProductMetadataData>()); Set<String> names = new
+ * HashSet<String>(); for (ProductMetadataData data :
+ * notCertifiedHighest) { String name =
+ * data.getMetadataDataDefinition().getName(); names.add(name); }
+ *
+ * for (ProductMetadataData data : certifiedHighest) { String
+ * productName = data.getMetadataDataDefinition().getName(); if
+ * (!names.contains(productName)) { notCertifiedHighest.add(data); }
+ * }
+ */
+ Either<List<ProductMetadataData>, TitanOperationStatus> listOfHighestComponents = this
+ .getListOfHighestComponents(NodeTypeEnum.Product, ProductMetadataData.class);
+ if (listOfHighestComponents.isRight()
+ && listOfHighestComponents.right().value() != TitanOperationStatus.NOT_FOUND) {
+ return Either.right(
+ DaoStatusConverter.convertTitanStatusToStorageStatus(listOfHighestComponents.right().value()));
+ }
+
+ List<ProductMetadataData> notCertifiedHighest = listOfHighestComponents.left().value();
+
+ List<Product> result = new ArrayList<>();
+
+ if (notCertifiedHighest != null && false == notCertifiedHighest.isEmpty()) {
+
+ // fetch from cache
+ long startFetchAllFromCache = System.currentTimeMillis();
+
+ Map<String, Long> components = notCertifiedHighest.stream()
+ .collect(Collectors.toMap(p -> p.getMetadataDataDefinition().getUniqueId(),
+ p -> p.getMetadataDataDefinition().getLastUpdateDate()));
+
+ Either<ImmutablePair<List<Component>, Set<String>>, ActionStatus> componentsFromCacheForCatalog = this
+ .getComponentsFromCacheForCatalog(components, ComponentTypeEnum.PRODUCT);
+ if (componentsFromCacheForCatalog.isLeft()) {
+ ImmutablePair<List<Component>, Set<String>> immutablePair = componentsFromCacheForCatalog.left()
+ .value();
+ List<Component> list = immutablePair.getLeft();
+ if (list != null) {
+ for (Component component : list) {
+ result.add((Product) component);
+ }
+ List<String> addedUids = list.stream()
+ .map(p -> p.getComponentMetadataDefinition().getMetadataDataDefinition().getUniqueId())
+ .collect(Collectors.toList());
+ notCertifiedHighest = notCertifiedHighest.stream()
+ .filter(p -> false == addedUids.contains(p.getMetadataDataDefinition().getUniqueId()))
+ .collect(Collectors.toList());
+ }
+ }
+ long endFetchAllFromCache = System.currentTimeMillis();
+ log.debug("Fetch all catalog products metadata from cache took {} ms",
+ (endFetchAllFromCache - startFetchAllFromCache));
+ log.debug("The number of products added to catalog from cache is {}", result.size());
+
+ log.debug("The number of products needed to be fetch as light component is {}",
+ notCertifiedHighest.size());
+
+ for (ProductMetadataData data : notCertifiedHighest) {
+ Either<Product, StorageOperationStatus> component = getLightComponent(
+ data.getMetadataDataDefinition().getUniqueId(), inTransaction);
+ if (component.isRight()) {
+ log.debug("Failed to get product for id = {}, error : {}. skip product", data.getUniqueId(),
+ component.right().value());
+ } else {
+ // get all versions
+ Product product = component.left().value();
+ // setAllVersions(product);
+
+ result.add(product);
+ }
+ }
+ }
+ return Either.left(result);
+ } finally {
+ if (false == inTransaction) {
+ titanGenericDao.commit();
+ }
+ log.debug("Fetch all catalog products took {} ms", (System.currentTimeMillis() - start));
+ }
+ }
+
+ @Override
+ public Either<Product, StorageOperationStatus> createProduct(Product product) {
+ return createProduct(product, false);
+ }
+
+ @Override
+ public Either<Product, StorageOperationStatus> createProduct(Product product, boolean inTransaction) {
+ Either<Product, StorageOperationStatus> result = null;
+
+ try {
+
+ ProductMetadataData productData = getProductMetadataDataFromProduct(product);
+ addComponentInternalFields(productData);
+ String uniqueId = (String) productData.getUniqueId();
+ generateUUID(product);
+
+ String userId = product.getCreatorUserId();
+
+ Either<UserData, TitanOperationStatus> findUser = findUser(userId);
+
+ if (findUser.isRight()) {
+ TitanOperationStatus status = findUser.right().value();
+ log.error("Cannot find user {} in the graph. status is {}", userId, status);
+ return sendError(status, StorageOperationStatus.USER_NOT_FOUND);
+ }
+
+ UserData creatorUserData = findUser.left().value();
+ UserData updaterUserData = creatorUserData;
+ String updaterUserId = product.getLastUpdaterUserId();
+ if (updaterUserId != null && !updaterUserId.equals(userId)) {
+ findUser = findUser(updaterUserId);
+ if (findUser.isRight()) {
+ TitanOperationStatus status = findUser.right().value();
+ log.error("Cannot find user {} in the graph. status is {}", userId, status);
+ return sendError(status, StorageOperationStatus.USER_NOT_FOUND);
+ } else {
+ updaterUserData = findUser.left().value();
+ }
+ }
+
+ log.trace("Creating tags for product {}", uniqueId);
+ StorageOperationStatus storageOperationStatus = createTagsForComponent(product);
+ if (storageOperationStatus != StorageOperationStatus.OK) {
+ return Either.right(storageOperationStatus);
+ }
+
+ log.trace("Finding groupings for product {}", uniqueId);
+ Either<List<GroupingData>, StorageOperationStatus> findGroupingsForComponent = findGroupingsForComponent(
+ NodeTypeEnum.ProductGrouping, product);
+ if (findGroupingsForComponent.isRight()) {
+ return Either.right(findGroupingsForComponent.right().value());
+ }
+ List<GroupingData> groupingDataToAssociate = findGroupingsForComponent.left().value();
+
+ log.debug("try to create product node on graph for id {}", uniqueId);
+ Either<ProductMetadataData, TitanOperationStatus> createNode = titanGenericDao.createNode(productData,
+ ProductMetadataData.class);
+ if (createNode.isRight()) {
+ TitanOperationStatus status = createNode.right().value();
+ log.error("Error returned after creating product data node {}. Status returned is {}", productData,
+ status);
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ log.debug("product node created on graph for id {}", productData.getUniqueId());
+
+ TitanOperationStatus associateMetadata = associateMetadataToComponent(productData, creatorUserData,
+ updaterUserData, null, null);
+ if (associateMetadata != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(associateMetadata));
+ return result;
+ }
+
+ TitanOperationStatus associateCategories = associateCategoriesToProduct(productData,
+ groupingDataToAssociate);
+ if (associateCategories != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(associateCategories));
+ return result;
+ }
+
+ result = getProduct(uniqueId, true);
+ if (result.isRight()) {
+ log.error("Cannot get full product from the graph. status is {}", result.right().value());
+ return Either.right(result.right().value());
+ }
+
+ if (log.isDebugEnabled()) {
+ String json = prettyJson.toJson(result.left().value());
+ log.debug("Product retrieved is {}", json);
+ }
+
+ return result;
+
+ } finally {
+ if (false == inTransaction) {
+ if (result == null || result.isRight()) {
+ log.debug("Going to execute rollback on graph.");
+ titanGenericDao.rollback();
+ } else {
+ log.debug("Going to execute commit on graph.");
+ titanGenericDao.commit();
+ }
+ }
+ }
+ }
+
+ private TitanOperationStatus associateCategoriesToProduct(ProductMetadataData productData,
+ List<GroupingData> groupingDataToAssociate) {
+ for (GroupingData groupingData : groupingDataToAssociate) {
+ GraphEdgeLabels groupingLabel = GraphEdgeLabels.CATEGORIZED_TO;
+ Either<GraphRelation, TitanOperationStatus> result = titanGenericDao.createRelation(productData,
+ groupingData, groupingLabel, null);
+ log.debug("After associating grouping {} to product {}. Edge type is {}", groupingData, productData,
+ groupingLabel);
+ if (result.isRight()) {
+ return result.right().value();
+ }
+ }
+ log.trace("All groupings associated succesfully to product {}", productData);
+ return TitanOperationStatus.OK;
+ }
+
+ private TitanOperationStatus dissociateCategoriesFromProduct(ProductMetadataData productData,
+ List<GroupingData> groupingDataToDissociate) {
+ for (GroupingData groupingData : groupingDataToDissociate) {
+ GraphEdgeLabels groupingLabel = GraphEdgeLabels.CATEGORIZED_TO;
+ Either<GraphRelation, TitanOperationStatus> result = titanGenericDao.deleteRelation(productData,
+ groupingData, groupingLabel);
+ log.debug("After dissociating grouping {} from product {}. Edge type is {}", groupingData, productData,
+ groupingLabel);
+ if (result.isRight()) {
+ return result.right().value();
+ }
+ }
+ log.trace("All groupings dissociated succesfully from product {}", productData);
+ return TitanOperationStatus.OK;
+ }
+
+ private Either<Product, StorageOperationStatus> getProduct(String uniqueId, boolean inTransaction) {
+ ComponentParametersView componentParametersView = new ComponentParametersView();
+ return getProduct(uniqueId, componentParametersView, inTransaction);
+ }
+
+ private Either<Product, StorageOperationStatus> getProduct(String uniqueId,
+ ComponentParametersView componentParametersView, boolean inTransaction) {
+ Product product = null;
+ Either<Product, StorageOperationStatus> result = null;
+ try {
+
+ NodeTypeEnum productNodeType = NodeTypeEnum.Product;
+ NodeTypeEnum compInstNodeType = NodeTypeEnum.Service;
+
+ Either<ProductMetadataData, StorageOperationStatus> getComponentByLabel = getComponentByLabelAndId(uniqueId,
+ productNodeType, ProductMetadataData.class);
+ if (getComponentByLabel.isRight()) {
+ result = Either.right(getComponentByLabel.right().value());
+ return result;
+ }
+ ProductMetadataData productData = getComponentByLabel.left().value();
+
+ // Try to fetch resource from the cache. The resource will be
+ // fetched only if the time on the cache equals to
+ // the time on the graph.
+ Either<Product, ActionStatus> componentFromCacheIfUpToDate = this.getComponentFromCacheIfUpToDate(uniqueId,
+ productData, componentParametersView, Product.class, ComponentTypeEnum.PRODUCT);
+ if (componentFromCacheIfUpToDate.isLeft()) {
+ Product cachedProduct = componentFromCacheIfUpToDate.left().value();
+ log.debug("Product {} with uid {} was fetched from cache.", cachedProduct.getName(),
+ cachedProduct.getUniqueId());
+ return Either.left(cachedProduct);
+ }
+
+ product = convertProductDataToProduct(productData);
+
+ TitanOperationStatus status = null;
+ if (false == componentParametersView.isIgnoreUsers()) {
+ status = setComponentCreatorFromGraph(product, uniqueId, productNodeType);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+
+ status = setComponentLastModifierFromGraph(product, uniqueId, productNodeType);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+
+ }
+ }
+ if (false == componentParametersView.isIgnoreCategories()) {
+ status = setComponentCategoriesFromGraph(product);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ }
+
+ if (false == componentParametersView.isIgnoreComponentInstances()
+ || false == componentParametersView.isIgnoreComponentInstancesProperties()
+ || false == componentParametersView.isIgnoreCapabilities()
+ || false == componentParametersView.isIgnoreRequirements()) {
+ status = setComponentInstancesFromGraph(uniqueId, product, productNodeType, compInstNodeType);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+
+ }
+ }
+ if (false == componentParametersView.isIgnoreComponentInstancesProperties()) {
+ status = setComponentInstancesPropertiesFromGraph(uniqueId, product);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ }
+ if (false == componentParametersView.isIgnoreCapabilities()) {
+ status = setCapabilitiesFromGraph(uniqueId, product, NodeTypeEnum.Product);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ }
+ if (false == componentParametersView.isIgnoreRequirements()) {
+ status = setRequirementsFromGraph(uniqueId, product, NodeTypeEnum.Product);
+ if (status != TitanOperationStatus.OK) {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ }
+
+ if (false == componentParametersView.isIgnoreAllVersions()) {
+ status = setAllVersions(product);
+ if (status != TitanOperationStatus.OK) {
+ return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ }
+ }
+
+ result = Either.left(product);
+ return result;
+
+ } finally {
+ if (false == inTransaction) {
+ if (result == null || result.isRight()) {
+ titanGenericDao.rollback();
+ } else {
+ titanGenericDao.commit();
+ }
+ }
+ }
+ }
+
+ // private Either<Product, StorageOperationStatus> getProduct_tx(String
+ // uniqueId, boolean inTransaction) {
+ // Product product = null;
+ // Either<Product, StorageOperationStatus> result = null;
+ // try {
+ //
+ // NodeTypeEnum productNodeType = NodeTypeEnum.Product;
+ // NodeTypeEnum compInstNodeType = NodeTypeEnum.Service;
+ //
+ // Either<ProductMetadataData, StorageOperationStatus> getComponentByLabel =
+ // getComponentByLabelAndId_tx(uniqueId, productNodeType,
+ // ProductMetadataData.class);
+ // if (getComponentByLabel.isRight()) {
+ // result = Either.right(getComponentByLabel.right().value());
+ // return result;
+ // }
+ // ProductMetadataData productData = getComponentByLabel.left().value();
+ // product = convertProductDataToProduct(productData);
+ //
+ // TitanOperationStatus status = setComponentCreatorFromGraph(product,
+ // uniqueId, productNodeType);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ // }
+ //
+ // status = setComponentLastModifierFromGraph(product, uniqueId,
+ // productNodeType);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ //
+ // }
+ // status = setComponentCategoriesFromGraph(product);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ // }
+ //
+ // status = setComponentInstancesFromGraph(uniqueId, product,
+ // productNodeType, compInstNodeType);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ //
+ // }
+ //
+ // status = setComponentInstancesPropertiesFromGraph(uniqueId, product);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ // }
+ //
+ // status = setCapabilitiesFromGraph(uniqueId, product,
+ // NodeTypeEnum.Product);
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ // }
+ //
+ // status = setRequirementsFromGraph( uniqueId, product,
+ // NodeTypeEnum.Product);;
+ // if (status != TitanOperationStatus.OK) {
+ // result =
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // return result;
+ // }
+ //
+ //
+ // status = setAllVersions(product);
+ // if (status != TitanOperationStatus.OK) {
+ // return
+ // Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ // }
+ //
+ // result = Either.left(product);
+ // return result;
+ //
+ // } finally {
+ // if (false == inTransaction) {
+ // if (result == null || result.isRight()) {
+ // titanGenericDao.rollback();
+ // } else {
+ // titanGenericDao.commit();
+ // }
+ // }
+ // }
+ // }
+
+ private TitanOperationStatus setAllVersions(Product product) {
+ Either<Map<String, String>, TitanOperationStatus> res = getVersionList(NodeTypeEnum.Product,
+ product.getVersion(), product, ProductMetadataData.class);
+ if (res.isRight()) {
+ return res.right().value();
+ }
+ product.setAllVersions(res.left().value());
+ return TitanOperationStatus.OK;
+ }
+
+ private Either<Product, StorageOperationStatus> sendError(TitanOperationStatus status,
+ StorageOperationStatus statusIfNotFound) {
+ Either<Product, StorageOperationStatus> result;
+ if (status == TitanOperationStatus.NOT_FOUND) {
+ result = Either.right(statusIfNotFound);
+ return result;
+ } else {
+ result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+ return result;
+ }
+ }
+
+ @Override
+ TitanOperationStatus setComponentCategoriesFromGraph(Component component) {
+ Product product = (Product) component;
+ // Building the cat->subcat->grouping triples
+ Either<List<ImmutablePair<GroupingData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao
+ .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Product), product.getUniqueId(),
+ GraphEdgeLabels.CATEGORIZED_TO, NodeTypeEnum.ProductGrouping, GroupingData.class);
+ if (childrenNodes.isRight()) {
+ if (childrenNodes.right().value() != TitanOperationStatus.NOT_FOUND) {
+ log.debug("Error when finding groupings for this product, error {}", childrenNodes.right().value());
+ return childrenNodes.right().value();
+ } else {
+ log.debug("No groupings found for this product - this might be normal");
+ return TitanOperationStatus.OK;
+ }
+ }
+ Map<CategoryDefinition, Map<SubCategoryDefinition, List<GroupingDefinition>>> categoriesDataStructure = new HashMap<>();
+
+ List<ImmutablePair<GroupingData, GraphEdge>> valueList = childrenNodes.left().value();
+ for (ImmutablePair<GroupingData, GraphEdge> groupPair : valueList) {
+ GroupingData groupingData = groupPair.getLeft();
+ Either<ImmutablePair<SubCategoryData, GraphEdge>, TitanOperationStatus> parentSubCat = titanGenericDao
+ .getParentNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ProductGrouping),
+ (String) groupingData.getUniqueId(), GraphEdgeLabels.GROUPING,
+ NodeTypeEnum.ProductSubcategory, SubCategoryData.class);
+ if (parentSubCat.isRight()) {
+ log.debug("Cannot find subcategory for grouping {}", groupingData.getUniqueId());
+ return parentSubCat.right().value();
+ }
+ SubCategoryData subCatData = parentSubCat.left().value().getLeft();
+ Either<ImmutablePair<CategoryData, GraphEdge>, TitanOperationStatus> parentCat = titanGenericDao
+ .getParentNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ProductSubcategory),
+ (String) subCatData.getUniqueId(), GraphEdgeLabels.SUB_CATEGORY,
+ NodeTypeEnum.ProductCategory, CategoryData.class);
+ if (parentCat.isRight()) {
+ log.debug("Cannot find category for subcategory {}", subCatData.getUniqueId());
+ return parentCat.right().value();
+ }
+
+ // Building data structure of categories hierarchy
+ CategoryDataDefinition categoryDefinition = parentCat.left().value().getLeft().getCategoryDataDefinition();
+ SubCategoryDataDefinition subDefinition = subCatData.getSubCategoryDataDefinition();
+ GroupingDataDefinition groupingDefinition = groupingData.getGroupingDataDefinition();
+
+ CategoryDefinition categoryDef = new CategoryDefinition(categoryDefinition);
+ SubCategoryDefinition subDef = new SubCategoryDefinition(subDefinition);
+ GroupingDefinition groupingDef = new GroupingDefinition(groupingDefinition);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Found category {} -> subcategory {} -> grouping {} for product {}",
+ categoryDefinition.getUniqueId(), subCatData.getUniqueId(), groupingData.getUniqueId(),
+ product.getUniqueId());
+ }
+ Map<SubCategoryDefinition, List<GroupingDefinition>> subMap = categoriesDataStructure.get(categoryDef);
+ if (subMap == null) {
+ subMap = new HashMap<>();
+ categoriesDataStructure.put(categoryDef, subMap);
+ }
+ List<GroupingDefinition> groupList = subMap.get(subDef);
+ if (groupList == null) {
+ groupList = new ArrayList<>();
+ subMap.put(subDef, groupList);
+ }
+ groupList.add(groupingDef);
+ }
+ convertToCategoriesList(product, categoriesDataStructure);
+ return TitanOperationStatus.OK;
+ }
+
+ private void convertToCategoriesList(Product product,
+ Map<CategoryDefinition, Map<SubCategoryDefinition, List<GroupingDefinition>>> categoriesDataStructure) {
+ List<CategoryDefinition> categoryDataList = product.getCategories();
+ if (categoryDataList == null) {
+ categoryDataList = new ArrayList<CategoryDefinition>();
+ }
+ for (Entry<CategoryDefinition, Map<SubCategoryDefinition, List<GroupingDefinition>>> triple : categoriesDataStructure
+ .entrySet()) {
+ CategoryDefinition categoryDefinition = triple.getKey();
+ List<SubCategoryDefinition> subList = new ArrayList<>();
+ categoryDefinition.setSubcategories(subList);
+ Map<SubCategoryDefinition, List<GroupingDefinition>> value = triple.getValue();
+
+ for (Entry<SubCategoryDefinition, List<GroupingDefinition>> pair : value.entrySet()) {
+ SubCategoryDefinition subCategoryDefinition = pair.getKey();
+ List<GroupingDefinition> list = pair.getValue();
+ subList.add(subCategoryDefinition);
+ subCategoryDefinition.setGroupings(list);
+ }
+ categoryDataList.add(categoryDefinition);
+ }
+ product.setCategories(categoryDataList);
+ log.debug("Fetched categories for product {}, categories: {}", product.getUniqueId(),
+ Arrays.toString(categoryDataList.toArray()));
+ }
+
+ private ProductMetadataData getProductMetadataDataFromProduct(Product product) {
+ ProductMetadataData productMetadata = new ProductMetadataData(
+ (ProductMetadataDataDefinition) product.getComponentMetadataDefinition().getMetadataDataDefinition());
+ return productMetadata;
+ }
+
+ @Override
+ public boolean isComponentExist(String id) {
+ return isComponentExist(id, NodeTypeEnum.Product);
+ }
+
+ // @SuppressWarnings("unchecked")
+ // @Override
+ // public <T> Either<T, StorageOperationStatus> cloneComponent(T other,
+ // String version, boolean inTransaction) {
+ // return (Either<T, StorageOperationStatus>) cloneProduct((Product)other,
+ // version, inTransaction);
+ // }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> Either<T, StorageOperationStatus> cloneComponent(T other, String version,
+ LifecycleStateEnum targetLifecycle, boolean inTransaction) {
+ return (Either<T, StorageOperationStatus>) cloneProduct((Product) other, version, targetLifecycle,
+ inTransaction);
+ }
+
+ private Either<Product, StorageOperationStatus> cloneProduct(Product other, String version,
+ LifecycleStateEnum targetLifecycle, boolean inTransaction) {
+ Either<Product, StorageOperationStatus> result = null;
+
+ try {
+ String origProductId = other.getUniqueId();
+ other.setVersion(version);
+ other.setUniqueId(null);
+
+ Either<Integer, StorageOperationStatus> counterStatus = getComponentInstanceCoutner(origProductId,
+ NodeTypeEnum.Product);
+ if (counterStatus.isRight()) {
+ StorageOperationStatus status = counterStatus.right().value();
+ log.error("failed to get resource instance counter on product {}. status={}", origProductId,
+ counterStatus);
+ result = Either.right(status);
+ return result;
+ }
+
+ Either<Product, StorageOperationStatus> createProductMD = createProduct(other, inTransaction);
+ if (createProductMD.isRight()) {
+ StorageOperationStatus status = createProductMD.right().value();
+ log.debug("Failed to clone product. status= {}", status);
+ result = Either.right(status);
+ return result;
+ }
+ Product product = createProductMD.left().value();
+
+ Either<ImmutablePair<List<ComponentInstance>, Map<String, String>>, StorageOperationStatus> cloneInstances = componentInstanceOperation.cloneAllComponentInstancesFromContainerComponent(origProductId, product,
+ NodeTypeEnum.Product, NodeTypeEnum.Service, targetLifecycle, null);
+ if (cloneInstances.isRight()) {
+ result = Either.right(cloneInstances.right().value());
+ return result;
+ }
+
+ Either<Integer, StorageOperationStatus> setResourceInstanceCounter = setComponentInstanceCounter(
+ product.getUniqueId(), NodeTypeEnum.Product, counterStatus.left().value(), inTransaction);
+ if (setResourceInstanceCounter.isRight()) {
+ StorageOperationStatus status = setResourceInstanceCounter.right().value();
+ log.error("failed to set resource instance counter on product {}. status={}", product.getUniqueId(),
+ setResourceInstanceCounter);
+ result = Either.right(status);
+ return result;
+ }
+
+ result = this.getProduct(product.getUniqueId(), inTransaction);
+ if (result.isRight()) {
+ log.error("Cannot get full product from the graph. status is {}", result.right().value());
+ return Either.right(result.right().value());
+ }
+
+ if (log.isDebugEnabled()) {
+ String json = prettyJson.toJson(result.left().value());
+ log.debug("Product retrieved is {}", json);
+ }
+
+ return result;
+ } finally {
+ if (false == inTransaction) {
+ if (result == null || result.isRight()) {
+ log.debug("Going to execute rollback on graph.");
+ titanGenericDao.rollback();
+ } else {
+ log.debug("Going to execute commit on graph.");
+ titanGenericDao.commit();
+ }
+ }
+ }
+ }
+
+ private Either<Product, StorageOperationStatus> getByNamesAndVersion(String nameKey, String nameValue,
+ String version, Map<String, Object> additionalParams, boolean inTransaction) {
+ Map<String, Object> props = new HashMap<String, Object>();
+ props.put(nameKey, nameValue);
+ props.put(GraphPropertiesDictionary.VERSION.getProperty(), version);
+ props.put(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.Product.getName());
+ if (additionalParams != null && !additionalParams.isEmpty()) {
+ props.putAll(additionalParams);
+ }
+
+ Either<List<ProductMetadataData>, TitanOperationStatus> byCriteria = titanGenericDao
+ .getByCriteria(NodeTypeEnum.Product, props, ProductMetadataData.class);
+
+ if (byCriteria.isRight()) {
+ return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
+ }
+ List<ProductMetadataData> dataList = byCriteria.left().value();
+ if (dataList != null && !dataList.isEmpty()) {
+ if (dataList.size() > 1) {
+ log.debug("More that one instance of product for name {} and version {}", nameValue, version);
+ return Either.right(StorageOperationStatus.GENERAL_ERROR);
+ }
+ ProductMetadataData productData = dataList.get(0);
+ Either<Product, StorageOperationStatus> product = getProduct(
+ productData.getMetadataDataDefinition().getUniqueId(), inTransaction);
+ if (product.isRight()) {
+ log.debug("Failed to fetch product, name {} id {}", productData.getMetadataDataDefinition().getName(),
+ productData.getMetadataDataDefinition().getUniqueId());
+ }
+ return product;
+ }
+ return Either.right(StorageOperationStatus.NOT_FOUND);
+ }
+
+ @Override
+ public Product getDefaultComponent() {
+ return new Product();
+ }
+
+ @Override
+ protected <T extends org.openecomp.sdc.be.model.Component> StorageOperationStatus updateDerived(
+ org.openecomp.sdc.be.model.Component component, org.openecomp.sdc.be.model.Component currentComponent,
+ ComponentMetadataData componentData, Class<T> clazz) {
+ log.debug("Derived class isn't supported for product");
+ return StorageOperationStatus.OK;
+ }
+
+ @Override
+ public Either<Integer, StorageOperationStatus> increaseAndGetComponentInstanceCounter(String componentId,
+ boolean inTransaction) {
+ return increaseAndGetComponentInstanceCounter(componentId, NodeTypeEnum.Product, inTransaction);
+ }
+
+ @Override
+ protected StorageOperationStatus validateCategories(Component currentComponent, Component component,
+ ComponentMetadataData componentData, NodeTypeEnum type) {
+ // As agreed with Ella, update categories - delete old and create new
+ StorageOperationStatus status = StorageOperationStatus.OK;
+ List<CategoryDefinition> newcategories = component.getCategories();
+ List<CategoryDefinition> currentcategories = currentComponent.getCategories();
+ if (newcategories != null) {
+ if (currentcategories != null && !currentcategories.isEmpty()) {
+ Either<List<GroupingData>, StorageOperationStatus> findGroupingsForComponent = findGroupingsForComponent(
+ NodeTypeEnum.ProductGrouping, currentComponent);
+ if (findGroupingsForComponent.isRight()) {
+ status = findGroupingsForComponent.right().value();
+ }
+ List<GroupingData> groupingDataToDissociate = findGroupingsForComponent.left().value();
+ TitanOperationStatus titanStatus = dissociateCategoriesFromProduct((ProductMetadataData) componentData,
+ groupingDataToDissociate);
+ if (titanStatus != TitanOperationStatus.OK) {
+ status = DaoStatusConverter.convertTitanStatusToStorageStatus(titanStatus);
+ }
+ }
+ if (!newcategories.isEmpty()) {
+ Either<List<GroupingData>, StorageOperationStatus> findGroupingsForComponent = findGroupingsForComponent(
+ NodeTypeEnum.ProductGrouping, component);
+ if (findGroupingsForComponent.isRight()) {
+ status = findGroupingsForComponent.right().value();
+ }
+ List<GroupingData> groupingDataToAssociate = findGroupingsForComponent.left().value();
+ TitanOperationStatus titanStatus = associateCategoriesToProduct((ProductMetadataData) componentData,
+ groupingDataToAssociate);
+ if (titanStatus != TitanOperationStatus.OK) {
+ status = DaoStatusConverter.convertTitanStatusToStorageStatus(titanStatus);
+ }
+ }
+ }
+ return status;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Either<List<Product>, StorageOperationStatus> getFollowed(String userId,
+ Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates, boolean inTransaction) {
+ return (Either<List<Product>, StorageOperationStatus>) (Either<?, StorageOperationStatus>) getFollowedComponent(
+ userId, lifecycleStates, lastStateStates, inTransaction, titanGenericDao, NodeTypeEnum.Product);
+ }
+
+ @Override
+ public Either<Component, StorageOperationStatus> getMetadataComponent(String id, boolean inTransaction) {
+ return getMetadataComponent(id, NodeTypeEnum.Product, inTransaction);
+ }
+
+ @Override
+ Component convertComponentMetadataDataToComponent(ComponentMetadataData componentMetadataData) {
+ return convertProductDataToProduct((ProductMetadataData) componentMetadataData);
+ }
+
+ @Override
+ public Either<Boolean, StorageOperationStatus> validateComponentNameExists(String productName) {
+ return validateComponentNameUniqueness(productName, titanGenericDao, NodeTypeEnum.Product);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Either<Component, StorageOperationStatus> markComponentToDelete(Component componentToDelete,
+ boolean inTransaction) {
+ // markComponentToDelete is not defined yet for products
+ return (Either<Component, StorageOperationStatus>) (Either<?, StorageOperationStatus>) deleteProduct(
+ componentToDelete.getUniqueId(), inTransaction);
+ }
+
+ @Override
+ public void rollback() {
+ titanGenericDao.rollback();
+
+ }
+
+ @Override
+ public void commit() {
+ titanGenericDao.commit();
+ }
+
+ @Override
+ public Either<Boolean, StorageOperationStatus> isComponentInUse(String componentId) {
+ return isComponentInUse(componentId, NodeTypeEnum.Product);
+ }
+
+ @Override
+ public Either<List<String>, StorageOperationStatus> getAllComponentsMarkedForDeletion() {
+ // markForDeletion for products is not implemented yet
+ return Either.left(new ArrayList<>());
+ }
+
+ public Either<Product, StorageOperationStatus> getProductByNameAndVersion(String productName, String productVersion,
+ boolean inTransaction) {
+ return getByNamesAndVersion(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(),
+ ValidationUtils.normaliseComponentName(productName), productVersion, null, inTransaction);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> Either<T, StorageOperationStatus> getComponent(String id,
+ ComponentParametersView componentParametersView, boolean inTransaction) {
+ return (Either<T, StorageOperationStatus>) getProduct(id, false);
+ }
+
+ public Either<Product, StorageOperationStatus> updateProduct(Product product, boolean inTransaction,
+ ComponentParametersView filterResultView) {
+ return (Either<Product, StorageOperationStatus>) updateComponentFilterResult(product, inTransaction,
+ titanGenericDao, product.getClass(), NodeTypeEnum.Service, filterResultView);
+ }
+
+ @Override
+ protected <T> Either<T, StorageOperationStatus> updateComponentFilterResult(T component, boolean inTransaction,
+ ComponentParametersView filterResultView) {
+ return (Either<T, StorageOperationStatus>) updateProduct((Product) component, inTransaction, filterResultView);
+ }
+}