[SDC-29] catalog 1707 rebase commit.
[sdc.git] / asdctool / src / main / java / org / openecomp / sdc / asdctool / impl / migration / v1707 / jsonmodel / ResourcesCategoriesMigration.java
1 package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel;
2
3 import fj.data.Either;
4 import org.openecomp.sdc.asdctool.impl.migration.MigrationMsg;
5 import org.openecomp.sdc.asdctool.impl.migration.Migration;
6 import org.openecomp.sdc.asdctool.impl.migration.v1707.MigrationUtils;
7 import org.openecomp.sdc.be.dao.api.ActionStatus;
8 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
9 import org.openecomp.sdc.be.datatypes.category.CategoryDataDefinition;
10 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
11 import org.openecomp.sdc.be.model.category.CategoryDefinition;
12 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
13 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
14
15 import javax.annotation.Resource;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.stream.Collectors;
20
21 import static org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.CategoriesUtils.filterOldCategories;
22 import static org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.CategoriesUtils.filterOldSubCategories;
23
24
25 public class ResourcesCategoriesMigration implements Migration {
26
27     @Resource(name = "element-operation")
28     private IElementOperation elementOperation;
29
30     @Resource(name = "element-operation-migration")
31     private IElementOperation elementOperationMigration;
32
33     @Resource(name = "titan-dao")
34     TitanDao titanDao;
35
36     @Override
37     public String description() {
38         return "migrate resource categories";
39     }
40
41     @Override
42     public boolean migrate() {
43         return getCategoriesToMigrate().either(this::migrateCategories,
44                                                errorStatus -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORIES.getMessage(errorStatus.name())));
45     }
46
47     private Either<List<CategoryDefinition>, ActionStatus> getCategoriesToMigrate() {
48         return elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
49     }
50
51     private boolean migrateCategories(List<CategoryDefinition> categoryDefinitions) {
52         List<CategoryDefinition> categoriesToMigrate = filterOldCategoriesAndSubCategories(categoryDefinitions);
53         for (CategoryDefinition categoryDefinition : categoriesToMigrate) {
54             boolean isMigrated = migrateCategoryIfNotExists(categoryDefinition);
55             if (!isMigrated) {
56                 titanDao.rollback();
57                 return false;
58             }
59             titanDao.commit();
60         }
61         return true;
62     }
63
64
65     //since production was malformed we need to fixed it by removing wrong categories and sub categories
66     private List<CategoryDefinition> filterOldCategoriesAndSubCategories(List<CategoryDefinition> categoryDefinitions) {
67         Map<String, List<CategoryDefinition>> categoriesByNormalName = categoryDefinitions.stream().collect(Collectors.groupingBy(CategoryDataDefinition::getNormalizedName));
68         List<CategoryDefinition> categoriesToMigrate = filterOldCategories(categoryDefinitions);
69         for (CategoryDefinition categoryDefinition : categoriesToMigrate) {
70             List<SubCategoryDefinition> newSubCategories = getAllDistinctSubCategories(categoriesByNormalName.get(categoryDefinition.getNormalizedName()));
71             categoryDefinition.setSubcategories(newSubCategories);
72         }
73         return categoriesToMigrate;
74     }
75
76     private List<SubCategoryDefinition> getAllDistinctSubCategories (List<CategoryDefinition> categoriesDefinitions) {
77         Map<String, List<SubCategoryDefinition>> subCategoriesByNormalName = categoriesDefinitions.stream().flatMap(ct -> ct.getSubcategories().stream()).collect(Collectors.groupingBy(SubCategoryDefinition::getNormalizedName));
78         return getDistinctSubCategories(subCategoriesByNormalName);
79     }
80
81     private List<SubCategoryDefinition> getDistinctSubCategories(Map<String, List<SubCategoryDefinition>> subCategoriesByNormalName) {
82         List<SubCategoryDefinition> allSubCategories = new ArrayList<>();
83         for (List<SubCategoryDefinition> subCategoryDefinitions : subCategoriesByNormalName.values()) {
84             if (subCategoryDefinitions.size() == 1) {
85                 allSubCategories.addAll(subCategoryDefinitions);
86             } else {
87                 allSubCategories.addAll(filterOldSubCategories(subCategoryDefinitions));
88             }
89         }
90         return allSubCategories;
91     }
92
93     private boolean migrateCategoryIfNotExists(CategoryDefinition categoryDefinition) {
94         return isExists(categoryDefinition).either(isExist -> isExist ? migrateSubCategories(categoryDefinition) : migrateCategoryAndSubCategories(categoryDefinition),
95                                                    error -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORY.getMessage(categoryDefinition.getName(), error.name())));
96     }
97
98     private boolean migrateCategoryAndSubCategories(CategoryDefinition resourceCategory) {
99         return elementOperationMigration.createCategory(resourceCategory, NodeTypeEnum.ResourceNewCategory)
100                 .either(createdCategory -> this.migrateSubCategories(resourceCategory),
101                         status -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_CREATE_CATEGORY.getMessage(resourceCategory.getName(), status.name())));
102     }
103
104     private boolean migrateSubCategories(CategoryDefinition categoryDefinition) {
105         for (SubCategoryDefinition subCategory : categoryDefinition.getSubcategories()) {
106             boolean isMigrated = migrateSubcategoryIfNotExists(categoryDefinition, subCategory);
107             if (!isMigrated) {
108                 return false;
109             }
110         }
111         return true;
112     }
113
114     private boolean migrateSubcategoryIfNotExists(CategoryDefinition parentCategory, SubCategoryDefinition subCategory) {
115         return isExists(subCategory).either(isExists -> isExists || migrateSubCategory(parentCategory, subCategory),
116                                             status -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_RETRIEVE_CATEGORY.getMessage(subCategory.getName(), status.name())));
117     }
118
119     private boolean migrateSubCategory(CategoryDefinition categoryDefinition, SubCategoryDefinition subCategory) {
120         return elementOperationMigration.createSubCategory(categoryDefinition.getUniqueId(), subCategory, NodeTypeEnum.ResourceSubcategory)
121                 .either(createdSubCategory -> true,
122                         errorStatus -> MigrationUtils.handleError(MigrationMsg.FAILED_TO_CREATE_SUB_CATEGORY.getMessage(subCategory.getName(), categoryDefinition.getName(), errorStatus.name())));
123
124     }
125
126     private Either<Boolean, ActionStatus> isExists(CategoryDefinition category) {
127         Either<CategoryDefinition, ActionStatus> byId = getCategoryById(category.getUniqueId());
128         return byId.either(existingVal -> Either.left(true),
129                            this::getEitherNotExistOrErrorStatus);
130     }
131
132     private Either<Boolean, ActionStatus> isExists(SubCategoryDefinition subCategory) {
133         return getSubCategoryById(subCategory.getUniqueId()).either(existingVal -> Either.left(true),
134                                                this::getEitherNotExistOrErrorStatus);
135     }
136
137     private Either<Boolean, ActionStatus> getEitherNotExistOrErrorStatus(ActionStatus status) {
138         return status == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND ? Either.left(false) : Either.right(status);
139     }
140
141     private Either<CategoryDefinition, ActionStatus> getCategoryById(String uid) {
142         return elementOperationMigration.getCategory(NodeTypeEnum.ResourceNewCategory, uid);
143     }
144
145     private Either<SubCategoryDefinition, ActionStatus> getSubCategoryById(String uid) {
146         return elementOperationMigration.getSubCategory(NodeTypeEnum.ResourceSubcategory, uid);
147     }
148
149
150 }