2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel;
23 import fj.data.Either;
24 import org.openecomp.sdc.asdctool.impl.migration.MigrationMsg;
25 import org.openecomp.sdc.asdctool.impl.migration.Migration1707Task;
26 import org.openecomp.sdc.asdctool.impl.migration.v1707.MigrationUtils;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
29 import org.openecomp.sdc.be.datatypes.category.CategoryDataDefinition;
30 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
31 import org.openecomp.sdc.be.model.category.CategoryDefinition;
32 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
33 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
34 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
36 import javax.annotation.Resource;
37 import java.util.ArrayList;
38 import java.util.List;
40 import java.util.stream.Collectors;
42 import static org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.CategoriesUtils.filterOldCategories;
43 import static org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.CategoriesUtils.filterOldSubCategories;
46 public class ResourcesCategoriesMigration implements Migration1707Task {
48 @Resource(name = "element-operation")
49 private IElementOperation elementOperation;
51 @Resource(name = "element-operation-migration")
52 private IElementOperation elementOperationMigration;
54 @Resource(name = "titan-dao")
58 public String description() {
59 return "migrate resource categories";
63 public boolean migrate() {
64 return getCategoriesToMigrate().either(this::migrateCategories,
65 errorStatus -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORIES.getMessage(errorStatus.name())));
68 private Either<List<CategoryDefinition>, ActionStatus> getCategoriesToMigrate() {
69 return elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
72 private boolean migrateCategories(List<CategoryDefinition> categoryDefinitions) {
73 List<CategoryDefinition> categoriesToMigrate = filterOldCategoriesAndSubCategories(categoryDefinitions);
74 for (CategoryDefinition categoryDefinition : categoriesToMigrate) {
75 boolean isMigrated = migrateCategoryIfNotExists(categoryDefinition);
86 //since production was malformed we need to fixed it by removing wrong categories and sub categories
87 private List<CategoryDefinition> filterOldCategoriesAndSubCategories(List<CategoryDefinition> categoryDefinitions) {
88 Map<String, List<CategoryDefinition>> categoriesByNormalName = categoryDefinitions.stream().collect(Collectors.groupingBy(CategoryDataDefinition::getNormalizedName));
89 List<CategoryDefinition> categoriesToMigrate = filterOldCategories(categoryDefinitions);
90 for (CategoryDefinition categoryDefinition : categoriesToMigrate) {
91 List<SubCategoryDefinition> newSubCategories = getAllDistinctSubCategories(categoriesByNormalName.get(categoryDefinition.getNormalizedName()));
92 categoryDefinition.setSubcategories(newSubCategories);
94 return categoriesToMigrate;
97 private List<SubCategoryDefinition> getAllDistinctSubCategories (List<CategoryDefinition> categoriesDefinitions) {
98 Map<String, List<SubCategoryDefinition>> subCategoriesByNormalName = categoriesDefinitions.stream()
99 .filter(ct -> ct.getSubcategories()!=null)
100 .flatMap(ct -> ct.getSubcategories().stream())
101 .collect(Collectors.groupingBy(SubCategoryDefinition::getNormalizedName));
102 return getDistinctSubCategories(subCategoriesByNormalName);
105 private List<SubCategoryDefinition> getDistinctSubCategories(Map<String, List<SubCategoryDefinition>> subCategoriesByNormalName) {
106 List<SubCategoryDefinition> allSubCategories = new ArrayList<>();
107 for (List<SubCategoryDefinition> subCategoryDefinitions : subCategoriesByNormalName.values()) {
108 if (subCategoryDefinitions.size() == 1) {
109 allSubCategories.addAll(subCategoryDefinitions);
111 allSubCategories.addAll(filterOldSubCategories(subCategoryDefinitions));
114 return allSubCategories;
117 private boolean migrateCategoryIfNotExists(CategoryDefinition categoryDefinition) {
118 return isExists(categoryDefinition).either(isExist -> isExist ? migrateSubCategories(categoryDefinition) : migrateCategoryAndSubCategories(categoryDefinition),
119 error -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORY.getMessage(categoryDefinition.getName(), error.name())));
122 private boolean migrateCategoryAndSubCategories(CategoryDefinition resourceCategory) {
123 return elementOperationMigration.createCategory(resourceCategory, NodeTypeEnum.ResourceNewCategory)
124 .either(createdCategory -> this.migrateSubCategories(resourceCategory),
125 status -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_CREATE_CATEGORY.getMessage(resourceCategory.getName(), status.name())));
128 private boolean migrateSubCategories(CategoryDefinition categoryDefinition) {
129 for (SubCategoryDefinition subCategory : categoryDefinition.getSubcategories()) {
130 boolean isMigrated = migrateSubcategoryIfNotExists(categoryDefinition, subCategory);
138 private boolean migrateSubcategoryIfNotExists(CategoryDefinition parentCategory, SubCategoryDefinition subCategory) {
139 return isExists(parentCategory, subCategory).either(isExists -> isExists || migrateSubCategory(parentCategory, subCategory),
140 status -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORY.getMessage(subCategory.getName(), status.name())));
143 private boolean migrateSubCategory(CategoryDefinition categoryDefinition, SubCategoryDefinition subCategory) {
144 return elementOperationMigration.createSubCategory(categoryDefinition.getUniqueId(), subCategory, NodeTypeEnum.ResourceSubcategory)
145 .either(createdSubCategory -> true,
146 errorStatus -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_CREATE_SUB_CATEGORY.getMessage(subCategory.getName(), categoryDefinition.getName(), errorStatus.name())));
150 private Either<Boolean, ActionStatus> isExists(CategoryDefinition category) {
151 Either<CategoryDefinition, ActionStatus> byId = getCategoryById(category);
152 return byId.either(existingVal -> Either.left(true),
153 this::getEitherNotExistOrErrorStatus);
156 private Either<Boolean, ActionStatus> isExists(CategoryDefinition parentCategory, SubCategoryDefinition subCategory) {
157 return getSubCategoryById(parentCategory, subCategory).either(existingVal -> Either.left(true),
158 this::getEitherNotExistOrErrorStatus);
161 private Either<Boolean, ActionStatus> getEitherNotExistOrErrorStatus(ActionStatus status) {
162 return status == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND ? Either.left(false) : Either.right(status);
165 private Either<CategoryDefinition, ActionStatus> getCategoryById(CategoryDefinition category) {
166 return elementOperationMigration.getCategory(NodeTypeEnum.ResourceNewCategory, category.getUniqueId());
169 private Either<SubCategoryDefinition, ActionStatus> getSubCategoryById(CategoryDefinition parentCategory, SubCategoryDefinition subCategory) {
170 String subCategoryUid = getExpectedSubCategoryId(parentCategory, subCategory);
171 return elementOperationMigration.getSubCategory(NodeTypeEnum.ResourceSubcategory, subCategoryUid);
174 //since a sub category might belong to a different category in old graph its new graph id is different than its old graph id
175 private String getExpectedSubCategoryId(CategoryDefinition parentCategory, SubCategoryDefinition subCategory) {
176 String parentId = UniqueIdBuilder.buildCategoryUid(parentCategory.getNormalizedName(), NodeTypeEnum.ResourceNewCategory);
177 return UniqueIdBuilder.buildSubCategoryUid(parentId, subCategory.getNormalizedName());