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.be.components.impl;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.EnumMap;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.LinkedList;
30 import java.util.List;
32 import java.util.Optional;
34 import java.util.function.Predicate;
35 import java.util.stream.Collectors;
37 import org.apache.commons.lang3.tuple.ImmutablePair;
38 import org.apache.http.NameValuePair;
39 import org.apache.http.client.utils.URLEncodedUtils;
40 import org.openecomp.sdc.be.dao.api.ActionStatus;
41 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
42 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
43 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
44 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
45 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
46 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
47 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
48 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
49 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
50 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
51 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
52 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
53 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
54 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
55 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
56 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
57 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
58 import org.openecomp.sdc.be.impl.ComponentsUtils;
59 import org.openecomp.sdc.be.model.ArtifactType;
60 import org.openecomp.sdc.be.model.Component;
61 import org.openecomp.sdc.be.model.ComponentParametersView;
62 import org.openecomp.sdc.be.model.DistributionStatusEnum;
63 import org.openecomp.sdc.be.model.LifecycleStateEnum;
64 import org.openecomp.sdc.be.model.Product;
65 import org.openecomp.sdc.be.model.PropertyScope;
66 import org.openecomp.sdc.be.model.Resource;
67 import org.openecomp.sdc.be.model.Service;
68 import org.openecomp.sdc.be.model.Tag;
69 import org.openecomp.sdc.be.model.User;
70 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
71 import org.openecomp.sdc.be.model.category.CategoryDefinition;
72 import org.openecomp.sdc.be.model.category.GroupingDefinition;
73 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
74 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
75 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
76 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
77 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
78 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
79 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
80 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
81 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
82 import org.openecomp.sdc.be.resources.data.category.CategoryData;
83 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
84 import org.openecomp.sdc.be.ui.model.UiCategories;
85 import org.openecomp.sdc.be.user.Role;
86 import org.openecomp.sdc.be.user.UserBusinessLogic;
87 import org.openecomp.sdc.common.datastructure.Wrapper;
88 import org.openecomp.sdc.common.util.ValidationUtils;
89 import org.openecomp.sdc.exception.ResponseFormat;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
93 import fj.data.Either;
95 @org.springframework.stereotype.Component("elementsBusinessLogic")
96 public class ElementBusinessLogic extends BaseBusinessLogic {
98 private static final Logger log = LoggerFactory.getLogger(ElementBusinessLogic.class);
100 @javax.annotation.Resource
101 private IElementOperation elementOperation;
103 @javax.annotation.Resource
104 private ComponentsUtils componentsUtils;
106 @javax.annotation.Resource
107 private UserBusinessLogic userAdminManager;
114 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
115 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
116 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
118 String role = user.getRole();
119 String userId = null;
120 Role currentRole = Role.valueOf(role);
122 switch (currentRole) {
124 userId = user.getUserId();
125 response = handleDesigner(userId);
129 userId = user.getUserId();
130 response = handleTester(userId);
134 userId = user.getUserId();
135 response = handleGovernor(userId);
139 userId = user.getUserId();
140 response = handleOps(userId);
143 case PRODUCT_STRATEGIST:
144 userId = user.getUserId();
145 response = handleProductStrategist(userId);
148 case PRODUCT_MANAGER:
149 userId = user.getUserId();
150 response = handleProductManager(userId);
154 response = handleAdmin();
158 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
161 // converting the Set to List so the rest of the code will handle it normally (Was changed because the same element with the same uuid was returned twice)
162 return convertedToListResponse(response);
166 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
168 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
169 if (setResponse.isLeft()) {
170 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
171 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
173 return Either.left(arrayResponse);
175 return Either.right(setResponse.right().value());
178 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
179 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
180 // userId should stay null
181 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
182 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
183 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
184 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
188 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
189 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
190 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
191 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
192 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
193 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
194 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
195 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
196 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
198 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
199 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
203 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor(String userId) {
204 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(null);
208 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist(String userId) {
209 // Should be empty list according to Ella, 13/03/16
210 Map<String, Set<? extends Component>> result = new HashMap<String, Set<? extends Component>>();
211 result.put("products", new HashSet<>());
212 return Either.left(result);
215 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
216 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
217 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
218 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
219 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
220 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
221 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
222 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
223 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
225 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
226 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
230 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps(String userId) {
231 Set<DistributionStatusEnum> distStatus = new HashSet<DistributionStatusEnum>();
232 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
233 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
235 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(distStatus);
239 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
241 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
242 if (services.isLeft()) {
243 Map<String, Set<? extends Component>> result = new HashMap<>();
244 Set<Service> set = new HashSet<>();
245 set.addAll(services.left().value());
246 result.put("services", set);
247 return Either.left(result);
249 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
253 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester(String userId) {
254 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
255 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
256 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
257 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = getFollowedResourcesAndServices(null, lifecycleStates, null);
262 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
265 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
267 if (resources.isLeft()) {
268 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
269 if (services.isLeft()) {
270 Map<String, Set<? extends Component>> result = new HashMap<String, Set<? extends Component>>();
271 result.put("services", services.left().value());
272 result.put("resources", resources.left().value());
273 return Either.left(result);
275 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
278 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
285 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
286 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
287 if (products.isLeft()) {
288 Map<String, Set<? extends Component>> result = new HashMap<>();
289 result.put("products", products.left().value());
290 return Either.left(result);
292 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
297 * New categories flow - start
299 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
300 return elementOperation.getAllResourceCategories();
303 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
304 return elementOperation.getAllServiceCategories();
307 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
309 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
310 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
311 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
312 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
314 User user = new User();
315 Either<User, ResponseFormat> validateUser = validateUser(userId);
316 if (validateUser.isRight()) {
317 log.debug("Validation of user failed, userId {}", userId);
318 ResponseFormat responseFormat = validateUser.right().value();
320 user.setUserId(userId);
321 String currCategoryName = (category == null ? null : category.getName());
322 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
323 return Either.right(responseFormat);
326 user = validateUser.left().value();
328 if (category == null) {
329 log.debug("Category json is invalid");
330 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
331 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
332 return Either.right(responseFormat);
335 String categoryName = category.getName();
336 // For auditing of failures we need the original non-normalized name
337 String origCategoryName = categoryName;
338 if (componentTypeEnum == null) {
339 log.debug("Component type {} is invalid", componentTypeParamName);
340 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
341 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
342 return Either.right(responseFormat);
345 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
346 if (validateUserRole.isRight()) {
347 log.debug("Validation of user role failed, userId {}", userId);
348 ResponseFormat responseFormat = validateUserRole.right().value();
349 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
350 return Either.right(responseFormat);
353 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
354 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
355 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
356 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
357 return Either.right(responseFormat);
360 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
362 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
363 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
364 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
365 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
366 return Either.right(responseFormat);
369 category.setName(categoryName);
371 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
372 category.setNormalizedName(normalizedName);
374 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
376 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
377 if (categoryUniqueEither.isRight()) {
378 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
379 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
380 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
381 return Either.right(responseFormat);
384 Boolean isCategoryUnique = categoryUniqueEither.left().value();
385 if (!isCategoryUnique) {
386 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
387 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
388 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
389 return Either.right(responseFormat);
392 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
393 if (createCategoryByType.isRight()) {
394 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
395 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
396 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
397 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
399 category = createCategoryByType.left().value();
400 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
401 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
402 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
403 return Either.left(category);
406 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
408 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
409 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
410 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
411 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
413 String parentCategoryName = parentCategoryId;
415 if (subCategory == null) {
416 log.debug("Sub-category json is invalid");
417 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
418 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
419 return Either.right(responseFormat);
422 String subCategoryName = subCategory.getName();
423 // For auditing of failures we need the original non-normalized name
424 String origSubCategoryName = subCategoryName;
426 User user = new User();
427 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "createSubCategory", false);
428 if (validateUser.isRight()) {
429 log.debug("Validation of user failed, userId {}", userId);
430 ResponseFormat responseFormat = validateUser.right().value();
432 user.setUserId(userId);
433 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
434 return Either.right(responseFormat);
437 user = validateUser.left().value();
439 if (componentTypeEnum == null) {
440 log.debug("Component type {} is invalid", componentTypeParamName);
441 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
442 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
443 return Either.right(responseFormat);
446 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
447 if (validateComponentType.isRight()) {
448 log.debug("Validation of component type for sub-category failed");
449 ResponseFormat responseFormat = validateComponentType.right().value();
450 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
451 return Either.right(responseFormat);
454 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
455 if (validateUserRole.isRight()) {
456 log.debug("Validation of user role failed, userId {}", userId);
457 ResponseFormat responseFormat = validateUserRole.right().value();
458 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
459 return Either.right(responseFormat);
462 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
463 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
465 CategoryDefinition categoryDefinition;
466 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
467 if (validateCategoryExists.isRight()) {
468 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
469 ResponseFormat responseFormat = validateCategoryExists.right().value();
470 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
471 return Either.right(responseFormat);
474 categoryDefinition = validateCategoryExists.left().value();
475 parentCategoryName = categoryDefinition.getName();
477 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
478 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
479 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
480 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
481 return Either.right(responseFormat);
484 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
486 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
487 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
488 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
489 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
490 return Either.right(responseFormat);
493 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
494 subCategory.setNormalizedName(normalizedName);
496 // Uniqueness under this category
497 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
498 if (subCategoryUniqueForCategory.isRight()) {
499 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
500 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
501 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
502 return Either.right(responseFormat);
505 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
507 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
508 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
509 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
510 return Either.right(responseFormat);
513 // Setting name of subcategory to fit the similar subcategory name
515 // For example if Network-->kUKU exists for service category Network,
516 // and user is trying to create Router-->Kuku for service category
518 // his subcategory name will be Router-->kUKU.
519 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
520 if (subCategoryUniqueForType.isRight()) {
521 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
522 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
523 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
524 return Either.right(responseFormat);
526 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
527 if (subCategoryDefinition != null) {
528 subCategoryName = subCategoryDefinition.getName();
531 subCategory.setName(subCategoryName);
532 ///////////////////////////////////////////// Validations end
534 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
535 if (createSubCategory.isRight()) {
536 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
537 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
538 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
539 return Either.right(responseFormat);
542 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
543 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
544 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
545 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
546 return Either.left(subCategoryCreated);
549 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
551 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
552 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
553 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
554 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
556 String parentCategoryName = grandParentCategoryId;
557 String parentSubCategoryName = parentSubCategoryId;
560 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "create Grouping", false);
561 if (validateUser.isRight()) {
562 log.debug("Validation of user failed, userId {}", userId);
563 ResponseFormat responseFormat = validateUser.right().value();
565 user.setUserId(userId);
566 String groupingNameForAudit = grouping == null ? null : grouping.getName();
567 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
568 return Either.right(responseFormat);
571 user = validateUser.left().value();
573 if (grouping == null) {
574 log.debug("Grouping json is invalid");
575 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
576 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
577 return Either.right(responseFormat);
580 String groupingName = grouping.getName();
581 // For auditing of failures we need the original non-normalized name
582 String origGroupingName = groupingName;
584 if (componentTypeEnum == null) {
585 log.debug("Component type {} is invalid", componentTypeParamName);
586 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
587 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
588 return Either.right(responseFormat);
591 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
592 if (validateComponentType.isRight()) {
593 log.debug("Validation of component type for grouping failed");
594 ResponseFormat responseFormat = validateComponentType.right().value();
595 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
596 return Either.right(responseFormat);
599 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
600 if (validateUserRole.isRight()) {
601 log.debug("Validation of user role failed, userId {}", userId);
602 ResponseFormat responseFormat = validateUserRole.right().value();
603 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
604 return Either.right(responseFormat);
607 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
608 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
609 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
612 CategoryDefinition categoryDefinition;
613 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
614 if (validateCategoryExists.isRight()) {
615 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
616 ResponseFormat responseFormat = validateCategoryExists.right().value();
617 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
618 return Either.right(responseFormat);
621 categoryDefinition = validateCategoryExists.left().value();
622 parentCategoryName = categoryDefinition.getName();
624 // Validate subcategory
625 SubCategoryDefinition subCategoryDefinition;
626 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
627 if (validateSubCategoryExists.isRight()) {
628 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
629 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
630 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
631 return Either.right(responseFormat);
634 subCategoryDefinition = validateSubCategoryExists.left().value();
635 parentSubCategoryName = subCategoryDefinition.getName();
637 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
638 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
639 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
640 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
641 return Either.right(responseFormat);
644 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
646 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
647 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
648 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
649 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
650 return Either.right(responseFormat);
653 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
654 grouping.setNormalizedName(normalizedName);
656 // Uniqueness under this category
657 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
658 if (groupingUniqueForSubCategory.isRight()) {
659 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
660 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
661 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
662 return Either.right(responseFormat);
665 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
666 if (!isGroupingUnique) {
667 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
668 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
669 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
670 return Either.right(responseFormat);
673 // Setting name of grouping to fit the similar grouping name ignoring
675 // For example if Network-->kUKU exists for service sub-category
676 // Network, and user is trying to create grouping Router-->Kuku for
677 // service sub-category Router,
678 // his grouping name will be Router-->kUKU.
679 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
680 if (groupingUniqueForType.isRight()) {
681 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
682 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
683 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
684 return Either.right(responseFormat);
686 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
687 if (groupingDefinition != null) {
688 groupingName = groupingDefinition.getName();
691 grouping.setName(groupingName);
692 ///////////////////////////////////////////// Validations end
694 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
695 if (createGrouping.isRight()) {
696 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
697 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
698 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
699 return Either.right(responseFormat);
702 GroupingDefinition groupingCreated = createGrouping.left().value();
703 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
704 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
705 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
706 return Either.left(groupingCreated);
709 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
710 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
711 ResponseFormat responseFormat;
712 User user = new User();
713 if (userId == null) {
714 user.setUserId("UNKNOWN");
715 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
716 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
717 return Either.right(responseFormat);
720 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "get All Categories", false);
721 if (validateUser.isRight()) {
722 user.setUserId(userId);
723 log.debug("Validation of user failed, userId {}", userId);
724 responseFormat = validateUser.right().value();
725 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
726 return Either.right(responseFormat);
728 user = validateUser.left().value();
730 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
731 if (componentTypeEnum == null) {
732 log.debug("Cannot create category for component type {}", componentType);
733 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
734 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
735 return Either.right(responseFormat);
738 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
739 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
740 if (getAllCategoriesByType.isRight()) {
741 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
742 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
743 return Either.right(responseFormat);
745 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
746 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
747 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
748 return Either.left(categories);
751 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
752 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
753 ResponseFormat responseFormat;
754 UiCategories categories = new UiCategories();
756 Either<User, ResponseFormat> userResponse = validateUserExists(userId, "get all categories", false);
758 if (userResponse.isRight()) {
759 return Either.right(userResponse.right().value());
761 User user = userResponse.left().value();
763 // GET resource categories
764 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
765 if (getResourceCategoriesByType.isRight()) {
766 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
767 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
768 return Either.right(responseFormat);
770 categories.setResourceCategories(getResourceCategoriesByType.left().value());
772 // GET service categories
773 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
774 if (getServiceCategoriesByType.isRight()) {
775 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
776 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
777 return Either.right(responseFormat);
779 categories.setServiceCategories(getServiceCategoriesByType.left().value());
781 // GET product categories
782 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
783 if (getProductCategoriesByType.isRight()) {
784 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
785 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
786 return Either.right(responseFormat);
789 categories.setProductCategories(getProductCategoriesByType.left().value());
790 return Either.left(categories);
794 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
796 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Category", false);
797 if (resp.isRight()) {
798 return Either.right(resp.right().value());
801 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
802 if (componentTypeEnum == null) {
803 log.debug("Cannot create category for component type {}", componentTypeParamName);
804 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
807 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
809 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
810 if (deleteCategoryByType.isRight()) {
811 // auditing, logging here...
812 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
814 CategoryDefinition category = deleteCategoryByType.left().value();
815 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
816 return Either.left(category);
819 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String grandParentCategoryId, String parentSubCategoryId, String componentTypeParamName, String userId) {
821 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Sub Category", false);
822 if (resp.isRight()) {
823 return Either.right(resp.right().value());
826 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
827 if (componentTypeEnum == null) {
828 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
829 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
832 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
834 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
835 if (deleteSubCategoryByType.isRight()) {
836 // auditing, logging here...
837 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
839 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
840 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
841 return Either.left(subCategory);
844 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String grandParentCategoryId, String parentSubCategoryId, String groupingId, String componentTypeParamName, String userId) {
846 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Grouping", false);
847 if (resp.isRight()) {
848 return Either.right(resp.right().value());
851 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
852 if (componentTypeEnum == null) {
853 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
854 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
857 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
859 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
860 if (deleteGroupingByType.isRight()) {
861 // auditing, logging here...
862 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
864 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
865 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
866 return Either.left(deletedGrouping);
869 private Either<User, ResponseFormat> validateUser(String userId) {
871 // validate user exists
872 if (userId == null) {
873 log.debug("UserId is null");
874 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
877 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
878 if (userResult.isRight()) {
879 ResponseFormat responseFormat;
880 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
881 log.debug("Not authorized user, userId = {}", userId);
882 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
884 log.debug("Failed to authorize user, userId = {}", userId);
885 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
888 return Either.right(responseFormat);
890 return Either.left(userResult.left().value());
891 // ========================================-
894 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
895 String role = user.getRole();
896 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
897 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
899 if (!(validAdminAction || validProductAction)) {
900 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
901 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
902 return Either.right(responseFormat);
904 return Either.left(true);
907 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
908 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
909 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
910 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
916 if (!(validResourceAction || validServiceAction || validProductAction)) {
917 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
918 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
919 return Either.right(responseFormat);
921 return Either.left(true);
924 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
925 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
926 if (categoryByTypeAndId.isRight()) {
927 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
928 ActionStatus actionStatus = categoryByTypeAndId.right().value();
929 ResponseFormat responseFormat;
930 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
931 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
933 responseFormat = componentsUtils.getResponseFormat(actionStatus);
935 return Either.right(responseFormat);
937 return Either.left(categoryByTypeAndId.left().value());
940 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
941 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
942 if (subCategoryByTypeAndId.isRight()) {
943 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
944 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
945 ResponseFormat responseFormat;
946 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
947 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
949 responseFormat = componentsUtils.getResponseFormat(actionStatus);
951 return Either.right(responseFormat);
953 return Either.left(subCategoryByTypeAndId.left().value());
956 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
957 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
960 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
961 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
964 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
965 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
969 * New categories flow - end
972 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
973 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
974 if (resp.isRight()) {
975 return Either.right(resp.right().value());
977 return elementOperation.getAllTags();
980 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
981 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
982 if (resp.isRight()) {
983 return Either.right(resp.right().value());
985 return elementOperation.getAllPropertyScopes();
988 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
989 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
990 if (resp.isRight()) {
991 return Either.right(resp.right().value());
993 return elementOperation.getAllArtifactTypes();
996 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
997 return elementOperation.getAllDeploymentArtifactTypes();
1000 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
1001 return elementOperation.getDefaultHeatTimeout();
1004 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId) {
1006 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Catalog Components", true);
1007 if (resp.isRight()) {
1008 return Either.right(resp.right().value());
1010 return toscaOperationFacade.getCatalogComponents().bimap(this::groupByComponentType, err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
1016 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
1017 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
1019 // fixed response for UI!!! UI need to receive always map!
1021 map = new HashMap<>();
1023 if (map.get("resources") == null) {
1024 map.put("resources", new ArrayList());
1026 if (map.get("services") == null) {
1027 map.put("services", new ArrayList());
1032 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
1033 switch (componentTypeEnum) {
1039 throw new IllegalStateException("resources or services only");
1043 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1044 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1046 if (query != null) {
1047 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1048 if (invalidFilter.isPresent()) {
1049 log.debug("getFilteredAssetList: invalid filter key");
1050 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1054 if (filters == null || filters.isEmpty()) {
1055 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1056 if (componentsList.isRight()) {
1057 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1059 return Either.left(componentsList.left().value());
1062 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1064 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1065 if (result.isRight()) {
1066 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1067 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1069 if (result.left().value().isEmpty()) {// no assets found for requested
1071 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1073 return Either.left(result.left().value());
1076 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1077 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1078 if (assetType == ComponentTypeEnum.RESOURCE) {
1080 assetResult = getFilteredResouces(filters, inTransaction);
1082 } else if (assetType == ComponentTypeEnum.SERVICE) {
1084 assetResult = getFilteredServices(filters, inTransaction);
1089 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1091 Either<List<T>, StorageOperationStatus> components = null;
1093 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1094 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1095 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1096 if (distributionStatus != null && distEnum == null) {
1097 filters.remove(FilterKeyEnum.CATEGORY);
1098 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1101 if (categoryName != null) { // primary filter
1102 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, GraphEdgeLabels.CATEGORY.getProperty(), NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1103 if (components.isLeft() && distEnum != null) {// secondary filter
1104 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1105 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1107 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1111 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1112 distStatusSet.add(distEnum);
1113 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1114 if (servicesWithDistStatus.isRight()) { // not found == empty list
1115 return Either.left(new ArrayList<>());
1118 return Either.left((List<T>) servicesWithDistStatus.left().value());
1121 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1123 if (assetType == null || uuid == null) {
1124 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1125 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1128 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1130 if (assetTypeEnum == null) {
1131 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1132 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1135 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1137 switch (assetTypeEnum) {
1139 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1142 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1145 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1146 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1149 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1150 if (componentsListByUuid.isRight()) {
1151 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1152 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1153 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1156 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1157 return Either.left(componentsListByUuid.left().value());
1160 public List<String> getAllComponentTypesParamNames() {
1161 List<String> paramNames = new ArrayList<>();
1162 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1163 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1164 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1168 public List<String> getAllSupportedRoles() {
1169 Role[] values = Role.values();
1170 List<String> roleNames = new ArrayList<>();
1171 for (Role role : values) {
1172 roleNames.add(role.name());
1177 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1178 return elementOperation.getResourceTypesMap();
1181 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1182 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1183 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1184 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1185 return params.stream().filter(noMatch).findAny();
1188 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1189 List<String> params = new ArrayList<String>();
1190 if (1 == filters.size()) {
1191 params.add(assetType.getValue().toLowerCase());
1192 params.add(filters.keySet().iterator().next().getName());
1193 params.add(filters.values().iterator().next());
1195 params.add(assetType.getValue());
1196 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1197 params.add(filters.get(FilterKeyEnum.CATEGORY));
1202 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1204 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1205 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1206 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1207 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1208 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1210 if (categoryName != null) {
1211 subcategories = getAllSubCategories(categoryName);
1212 if (subcategories.isRight()) {
1213 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1214 return Either.right(subcategories.right().value());
1217 if (subCategoryName != null) { // primary filter
1218 if (categoryName != null) {
1219 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1220 if (!subCategoryData.isPresent()) {
1221 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1223 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction,
1224 ResourceMetadataData.class, resourceType);
1227 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1229 if (subcategories != null) {
1230 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1232 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1235 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1236 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1237 if (categoryResult.isRight()) {
1238 return Either.right(categoryResult.right().value());
1240 CategoryData categoryData = categoryResult.left().value();
1242 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1243 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1244 if (childrenNodes.isRight()) {
1245 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1247 return Either.left(childrenNodes.left().value());
1250 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1251 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1252 return childNodes.stream().filter(matchName).findAny();
1255 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1256 Class<S> clazz, ResourceTypeEnum resourceType) {
1258 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1260 if (false == inTransaction) {
1266 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1267 Class<S> clazz, ResourceTypeEnum resourceType) {
1268 List<T> components = new ArrayList<>();
1270 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1271 Map<String, Object> props = new HashMap<String, Object>();
1272 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1273 Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1274 if (getCategory.isRight()) {
1275 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1277 for (GraphNode category : getCategory.left().value()) {
1278 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1279 if (result.isRight()) {
1282 components.addAll(result.left().value());
1285 return Either.left(components);
1287 if (false == inTransaction) {
1293 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1294 List<T> components = new ArrayList<>();
1295 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1296 if (parentNodes.isLeft()) {
1297 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1298 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1299 Boolean isHighest = componentData.isHighestVersion();
1300 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1301 boolean isDeleted = componentData.isDeleted() != null && componentData.isDeleted();
1303 if (isHighest && isMatchingResourceType && !isDeleted) {
1304 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1305 if (result.isRight()) {
1306 return Either.right(result.right().value());
1308 components.add(result.left().value());
1312 return Either.left(components);
1315 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1318 if (componentType == NodeTypeEnum.Resource) {
1319 if (resourceType == null) {
1322 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1330 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1331 List<T> components = new ArrayList<>();
1333 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1334 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource,
1335 inTransaction, ResourceMetadataData.class, resourceType);
1336 if (fetched.isRight()) {
1339 components.addAll(fetched.left().value());
1341 return Either.left(components);
1344 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1345 List<Component> components = null;
1346 StorageOperationStatus status;
1347 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1348 Either<List<Component>, StorageOperationStatus> result;
1350 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1351 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1352 if (getResources.isRight()) {
1353 status = getResources.right().value();
1354 if (status != StorageOperationStatus.NOT_FOUND) {
1355 statusWrapper.setInnerElement(getResources.right().value());
1357 components = new ArrayList<>();
1360 components = getResources.left().value();
1362 if (!statusWrapper.isEmpty()) {
1363 result = Either.right(statusWrapper.getInnerElement());
1365 result = Either.left(components);
1369 if (!inTransaction) {