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 fj.data.Either;
24 import org.apache.commons.lang3.tuple.ImmutablePair;
25 import org.apache.http.NameValuePair;
26 import org.apache.http.client.utils.URLEncodedUtils;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
29 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
30 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
31 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
32 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
33 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
34 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
35 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
36 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
37 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
39 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
40 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
41 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
42 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
43 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
44 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
45 import org.openecomp.sdc.be.impl.ComponentsUtils;
46 import org.openecomp.sdc.be.model.ArtifactType;
47 import org.openecomp.sdc.be.model.Component;
48 import org.openecomp.sdc.be.model.ComponentParametersView;
49 import org.openecomp.sdc.be.model.DistributionStatusEnum;
50 import org.openecomp.sdc.be.model.LifecycleStateEnum;
51 import org.openecomp.sdc.be.model.Product;
52 import org.openecomp.sdc.be.model.PropertyScope;
53 import org.openecomp.sdc.be.model.Resource;
54 import org.openecomp.sdc.be.model.Service;
55 import org.openecomp.sdc.be.model.Tag;
56 import org.openecomp.sdc.be.model.User;
57 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
58 import org.openecomp.sdc.be.model.category.CategoryDefinition;
59 import org.openecomp.sdc.be.model.category.GroupingDefinition;
60 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
61 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
62 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
63 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
64 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
65 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
66 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
67 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
68 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
69 import org.openecomp.sdc.be.resources.data.category.CategoryData;
70 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
71 import org.openecomp.sdc.be.ui.model.UiCategories;
72 import org.openecomp.sdc.be.user.Role;
73 import org.openecomp.sdc.be.user.UserBusinessLogic;
74 import org.openecomp.sdc.common.datastructure.Wrapper;
75 import org.openecomp.sdc.common.util.ValidationUtils;
76 import org.openecomp.sdc.exception.ResponseFormat;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 import java.nio.charset.StandardCharsets;
81 import java.util.ArrayList;
82 import java.util.Arrays;
83 import java.util.EnumMap;
84 import java.util.HashMap;
85 import java.util.HashSet;
86 import java.util.LinkedList;
87 import java.util.List;
89 import java.util.Optional;
91 import java.util.function.Predicate;
92 import java.util.stream.Collectors;
94 @org.springframework.stereotype.Component("elementsBusinessLogic")
95 public class ElementBusinessLogic extends BaseBusinessLogic {
97 private static final Logger log = LoggerFactory.getLogger(ElementBusinessLogic.class);
99 @javax.annotation.Resource
100 private IElementOperation elementOperation;
102 @javax.annotation.Resource
103 private ComponentsUtils componentsUtils;
105 @javax.annotation.Resource
106 private UserBusinessLogic userAdminManager;
113 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
114 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
115 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
117 String role = user.getRole();
118 String userId = null;
119 Role currentRole = Role.valueOf(role);
121 switch (currentRole) {
123 userId = user.getUserId();
124 response = handleDesigner(userId);
128 userId = user.getUserId();
129 response = handleTester(userId);
133 userId = user.getUserId();
134 response = handleGovernor(userId);
138 userId = user.getUserId();
139 response = handleOps(userId);
142 case PRODUCT_STRATEGIST:
143 userId = user.getUserId();
144 response = handleProductStrategist(userId);
147 case PRODUCT_MANAGER:
148 userId = user.getUserId();
149 response = handleProductManager(userId);
153 response = handleAdmin();
157 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
160 // 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)
161 return convertedToListResponse(response);
165 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
167 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
168 if (setResponse.isLeft()) {
169 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
170 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
172 return Either.left(arrayResponse);
174 return Either.right(setResponse.right().value());
177 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
178 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
179 // userId should stay null
180 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
181 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
182 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
183 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
187 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
188 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
189 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
190 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
191 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
192 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
193 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
194 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
195 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
197 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
198 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
202 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor(String userId) {
203 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(null);
207 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist(String userId) {
208 // Should be empty list according to Ella, 13/03/16
209 Map<String, Set<? extends Component>> result = new HashMap<String, Set<? extends Component>>();
210 result.put("products", new HashSet<>());
211 return Either.left(result);
214 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
215 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
216 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
217 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
218 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
219 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
220 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
221 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
222 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
224 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
225 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
229 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps(String userId) {
230 Set<DistributionStatusEnum> distStatus = new HashSet<DistributionStatusEnum>();
231 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
232 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
234 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(distStatus);
238 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
240 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
241 if (services.isLeft()) {
242 Map<String, Set<? extends Component>> result = new HashMap<>();
243 Set<Service> set = new HashSet<>();
244 set.addAll(services.left().value());
245 result.put("services", set);
246 return Either.left(result);
248 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
252 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester(String userId) {
253 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
254 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
255 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
256 Either<Map<String, Set<? extends Component>>, ResponseFormat> result = getFollowedResourcesAndServices(null, lifecycleStates, null);
261 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
264 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
266 if (resources.isLeft()) {
267 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
268 if (services.isLeft()) {
269 Map<String, Set<? extends Component>> result = new HashMap<String, Set<? extends Component>>();
270 result.put("services", services.left().value());
271 result.put("resources", resources.left().value());
272 return Either.left(result);
274 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
277 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
284 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
285 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
286 if (products.isLeft()) {
287 Map<String, Set<? extends Component>> result = new HashMap<>();
288 result.put("products", products.left().value());
289 return Either.left(result);
291 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
296 * New categories flow - start
298 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
299 return elementOperation.getAllResourceCategories();
302 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
303 return elementOperation.getAllServiceCategories();
306 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
308 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
309 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
310 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
311 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
313 User user = new User();
314 Either<User, ResponseFormat> validateUser = validateUser(userId);
315 if (validateUser.isRight()) {
316 log.debug("Validation of user failed, userId {}", userId);
317 ResponseFormat responseFormat = validateUser.right().value();
319 user.setUserId(userId);
320 String currCategoryName = (category == null ? null : category.getName());
321 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
322 return Either.right(responseFormat);
325 user = validateUser.left().value();
327 if (category == null) {
328 log.debug("Category json is invalid");
329 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
330 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
331 return Either.right(responseFormat);
334 String categoryName = category.getName();
335 // For auditing of failures we need the original non-normalized name
336 String origCategoryName = categoryName;
337 if (componentTypeEnum == null) {
338 log.debug("Component type {} is invalid", componentTypeParamName);
339 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
340 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
341 return Either.right(responseFormat);
344 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
345 if (validateUserRole.isRight()) {
346 log.debug("Validation of user role failed, userId {}", userId);
347 ResponseFormat responseFormat = validateUserRole.right().value();
348 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
349 return Either.right(responseFormat);
352 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
353 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
354 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
355 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
356 return Either.right(responseFormat);
359 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
361 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
362 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
363 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
364 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
365 return Either.right(responseFormat);
368 category.setName(categoryName);
370 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
371 category.setNormalizedName(normalizedName);
373 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
375 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
376 if (categoryUniqueEither.isRight()) {
377 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
378 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
379 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
380 return Either.right(responseFormat);
383 Boolean isCategoryUnique = categoryUniqueEither.left().value();
384 if (!isCategoryUnique) {
385 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
386 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
387 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
388 return Either.right(responseFormat);
391 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
392 if (createCategoryByType.isRight()) {
393 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
394 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
395 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
396 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
398 category = createCategoryByType.left().value();
399 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
400 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
401 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
402 return Either.left(category);
405 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
407 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
408 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
409 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
410 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
412 String parentCategoryName = parentCategoryId;
414 if (subCategory == null) {
415 log.debug("Sub-category json is invalid");
416 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
417 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
418 return Either.right(responseFormat);
421 String subCategoryName = subCategory.getName();
422 // For auditing of failures we need the original non-normalized name
423 String origSubCategoryName = subCategoryName;
425 User user = new User();
426 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "createSubCategory", false);
427 if (validateUser.isRight()) {
428 log.debug("Validation of user failed, userId {}", userId);
429 ResponseFormat responseFormat = validateUser.right().value();
431 user.setUserId(userId);
432 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
433 return Either.right(responseFormat);
436 user = validateUser.left().value();
438 if (componentTypeEnum == null) {
439 log.debug("Component type {} is invalid", componentTypeParamName);
440 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
441 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
442 return Either.right(responseFormat);
445 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
446 if (validateComponentType.isRight()) {
447 log.debug("Validation of component type for sub-category failed");
448 ResponseFormat responseFormat = validateComponentType.right().value();
449 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
450 return Either.right(responseFormat);
453 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
454 if (validateUserRole.isRight()) {
455 log.debug("Validation of user role failed, userId {}", userId);
456 ResponseFormat responseFormat = validateUserRole.right().value();
457 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
458 return Either.right(responseFormat);
461 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
462 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
464 CategoryDefinition categoryDefinition;
465 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
466 if (validateCategoryExists.isRight()) {
467 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
468 ResponseFormat responseFormat = validateCategoryExists.right().value();
469 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
470 return Either.right(responseFormat);
473 categoryDefinition = validateCategoryExists.left().value();
474 parentCategoryName = categoryDefinition.getName();
476 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
477 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
478 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
479 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
480 return Either.right(responseFormat);
483 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
485 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
486 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
487 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
488 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
489 return Either.right(responseFormat);
492 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
493 subCategory.setNormalizedName(normalizedName);
495 // Uniqueness under this category
496 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
497 if (subCategoryUniqueForCategory.isRight()) {
498 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
499 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
500 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
501 return Either.right(responseFormat);
504 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
506 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
507 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
508 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
509 return Either.right(responseFormat);
512 // Setting name of subcategory to fit the similar subcategory name
514 // For example if Network-->kUKU exists for service category Network,
515 // and user is trying to create Router-->Kuku for service category
517 // his subcategory name will be Router-->kUKU.
518 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
519 if (subCategoryUniqueForType.isRight()) {
520 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
521 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
522 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
523 return Either.right(responseFormat);
525 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
526 if (subCategoryDefinition != null) {
527 subCategoryName = subCategoryDefinition.getName();
530 subCategory.setName(subCategoryName);
531 ///////////////////////////////////////////// Validations end
533 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
534 if (createSubCategory.isRight()) {
535 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
536 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
537 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
538 return Either.right(responseFormat);
541 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
542 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
543 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
544 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
545 return Either.left(subCategoryCreated);
548 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
550 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
551 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
552 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
553 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
555 String parentCategoryName = grandParentCategoryId;
556 String parentSubCategoryName = parentSubCategoryId;
559 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "create Grouping", false);
560 if (validateUser.isRight()) {
561 log.debug("Validation of user failed, userId {}", userId);
562 ResponseFormat responseFormat = validateUser.right().value();
564 user.setUserId(userId);
565 String groupingNameForAudit = grouping == null ? null : grouping.getName();
566 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
567 return Either.right(responseFormat);
570 user = validateUser.left().value();
572 if (grouping == null) {
573 log.debug("Grouping json is invalid");
574 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
575 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
576 return Either.right(responseFormat);
579 String groupingName = grouping.getName();
580 // For auditing of failures we need the original non-normalized name
581 String origGroupingName = groupingName;
583 if (componentTypeEnum == null) {
584 log.debug("Component type {} is invalid", componentTypeParamName);
585 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
586 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
587 return Either.right(responseFormat);
590 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
591 if (validateComponentType.isRight()) {
592 log.debug("Validation of component type for grouping failed");
593 ResponseFormat responseFormat = validateComponentType.right().value();
594 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
595 return Either.right(responseFormat);
598 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
599 if (validateUserRole.isRight()) {
600 log.debug("Validation of user role failed, userId {}", userId);
601 ResponseFormat responseFormat = validateUserRole.right().value();
602 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
603 return Either.right(responseFormat);
606 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
607 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
608 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
611 CategoryDefinition categoryDefinition;
612 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
613 if (validateCategoryExists.isRight()) {
614 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
615 ResponseFormat responseFormat = validateCategoryExists.right().value();
616 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
617 return Either.right(responseFormat);
620 categoryDefinition = validateCategoryExists.left().value();
621 parentCategoryName = categoryDefinition.getName();
623 // Validate subcategory
624 SubCategoryDefinition subCategoryDefinition;
625 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
626 if (validateSubCategoryExists.isRight()) {
627 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
628 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
629 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
630 return Either.right(responseFormat);
633 subCategoryDefinition = validateSubCategoryExists.left().value();
634 parentSubCategoryName = subCategoryDefinition.getName();
636 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
637 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
638 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
639 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
640 return Either.right(responseFormat);
643 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
645 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
646 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
647 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
648 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
649 return Either.right(responseFormat);
652 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
653 grouping.setNormalizedName(normalizedName);
655 // Uniqueness under this category
656 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
657 if (groupingUniqueForSubCategory.isRight()) {
658 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
659 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
660 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
661 return Either.right(responseFormat);
664 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
665 if (!isGroupingUnique) {
666 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
667 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
668 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
669 return Either.right(responseFormat);
672 // Setting name of grouping to fit the similar grouping name ignoring
674 // For example if Network-->kUKU exists for service sub-category
675 // Network, and user is trying to create grouping Router-->Kuku for
676 // service sub-category Router,
677 // his grouping name will be Router-->kUKU.
678 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
679 if (groupingUniqueForType.isRight()) {
680 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
681 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
682 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
683 return Either.right(responseFormat);
685 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
686 if (groupingDefinition != null) {
687 groupingName = groupingDefinition.getName();
690 grouping.setName(groupingName);
691 ///////////////////////////////////////////// Validations end
693 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
694 if (createGrouping.isRight()) {
695 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
696 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
697 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
698 return Either.right(responseFormat);
701 GroupingDefinition groupingCreated = createGrouping.left().value();
702 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
703 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
704 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
705 return Either.left(groupingCreated);
708 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
709 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
710 ResponseFormat responseFormat;
711 User user = new User();
712 if (userId == null) {
713 user.setUserId("UNKNOWN");
714 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
715 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
716 return Either.right(responseFormat);
719 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "get All Categories", false);
720 if (validateUser.isRight()) {
721 user.setUserId(userId);
722 log.debug("Validation of user failed, userId {}", userId);
723 responseFormat = validateUser.right().value();
724 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
725 return Either.right(responseFormat);
727 user = validateUser.left().value();
729 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
730 if (componentTypeEnum == null) {
731 log.debug("Cannot create category for component type {}", componentType);
732 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
733 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
734 return Either.right(responseFormat);
737 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
738 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
739 if (getAllCategoriesByType.isRight()) {
740 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
741 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
742 return Either.right(responseFormat);
744 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
745 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
746 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
747 return Either.left(categories);
750 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
751 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
752 ResponseFormat responseFormat;
753 UiCategories categories = new UiCategories();
755 Either<User, ResponseFormat> userResponse = validateUserExists(userId, "get all categories", false);
757 if (userResponse.isRight()) {
758 return Either.right(userResponse.right().value());
760 User user = userResponse.left().value();
762 // GET resource categories
763 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
764 if (getResourceCategoriesByType.isRight()) {
765 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
766 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
767 return Either.right(responseFormat);
769 categories.setResourceCategories(getResourceCategoriesByType.left().value());
771 // GET service categories
772 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
773 if (getServiceCategoriesByType.isRight()) {
774 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
775 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
776 return Either.right(responseFormat);
778 categories.setServiceCategories(getServiceCategoriesByType.left().value());
780 // GET product categories
781 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
782 if (getProductCategoriesByType.isRight()) {
783 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
784 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
785 return Either.right(responseFormat);
788 categories.setProductCategories(getProductCategoriesByType.left().value());
789 return Either.left(categories);
793 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
795 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Category", false);
796 if (resp.isRight()) {
797 return Either.right(resp.right().value());
800 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
801 if (componentTypeEnum == null) {
802 log.debug("Cannot create category for component type {}", componentTypeParamName);
803 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
806 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
808 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
809 if (deleteCategoryByType.isRight()) {
810 // auditing, logging here...
811 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
813 CategoryDefinition category = deleteCategoryByType.left().value();
814 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
815 return Either.left(category);
818 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String grandParentCategoryId, String parentSubCategoryId, String componentTypeParamName, String userId) {
820 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Sub Category", false);
821 if (resp.isRight()) {
822 return Either.right(resp.right().value());
825 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
826 if (componentTypeEnum == null) {
827 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
828 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
831 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
833 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
834 if (deleteSubCategoryByType.isRight()) {
835 // auditing, logging here...
836 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
838 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
839 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
840 return Either.left(subCategory);
843 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String grandParentCategoryId, String parentSubCategoryId, String groupingId, String componentTypeParamName, String userId) {
845 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Grouping", false);
846 if (resp.isRight()) {
847 return Either.right(resp.right().value());
850 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
851 if (componentTypeEnum == null) {
852 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
853 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
856 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
858 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
859 if (deleteGroupingByType.isRight()) {
860 // auditing, logging here...
861 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
863 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
864 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
865 return Either.left(deletedGrouping);
868 private Either<User, ResponseFormat> validateUser(String userId) {
870 // validate user exists
871 if (userId == null) {
872 log.debug("UserId is null");
873 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
876 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
877 if (userResult.isRight()) {
878 ResponseFormat responseFormat;
879 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
880 log.debug("Not authorized user, userId = {}", userId);
881 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
883 log.debug("Failed to authorize user, userId = {}", userId);
884 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
887 return Either.right(responseFormat);
889 return Either.left(userResult.left().value());
890 // ========================================-
893 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
894 String role = user.getRole();
895 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
896 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
898 if (!(validAdminAction || validProductAction)) {
899 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
900 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
901 return Either.right(responseFormat);
903 return Either.left(true);
906 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
907 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
908 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
909 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
915 if (!(validResourceAction || validServiceAction || validProductAction)) {
916 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
917 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
918 return Either.right(responseFormat);
920 return Either.left(true);
923 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
924 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
925 if (categoryByTypeAndId.isRight()) {
926 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
927 ActionStatus actionStatus = categoryByTypeAndId.right().value();
928 ResponseFormat responseFormat;
929 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
930 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
932 responseFormat = componentsUtils.getResponseFormat(actionStatus);
934 return Either.right(responseFormat);
936 return Either.left(categoryByTypeAndId.left().value());
939 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
940 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
941 if (subCategoryByTypeAndId.isRight()) {
942 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
943 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
944 ResponseFormat responseFormat;
945 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
946 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
948 responseFormat = componentsUtils.getResponseFormat(actionStatus);
950 return Either.right(responseFormat);
952 return Either.left(subCategoryByTypeAndId.left().value());
955 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
956 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
959 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
960 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
963 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
964 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
968 * New categories flow - end
971 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
972 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
973 if (resp.isRight()) {
974 return Either.right(resp.right().value());
976 return elementOperation.getAllTags();
979 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
980 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
981 if (resp.isRight()) {
982 return Either.right(resp.right().value());
984 return elementOperation.getAllPropertyScopes();
987 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
988 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
989 if (resp.isRight()) {
990 return Either.right(resp.right().value());
992 return elementOperation.getAllArtifactTypes();
995 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
996 return elementOperation.getAllDeploymentArtifactTypes();
999 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
1000 return elementOperation.getDefaultHeatTimeout();
1003 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId) {
1005 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Catalog Components", true);
1006 if (resp.isRight()) {
1007 return Either.right(resp.right().value());
1009 return toscaOperationFacade.getCatalogComponents().bimap(this::groupByComponentType, err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
1015 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
1016 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
1018 // fixed response for UI!!! UI need to receive always map!
1020 map = new HashMap<>();
1022 if (map.get("resources") == null) {
1023 map.put("resources", new ArrayList());
1025 if (map.get("services") == null) {
1026 map.put("services", new ArrayList());
1031 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
1032 switch (componentTypeEnum) {
1038 throw new IllegalStateException("resources or services only");
1042 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1043 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1045 if (query != null) {
1046 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1047 if (invalidFilter.isPresent()) {
1048 log.debug("getFilteredAssetList: invalid filter key");
1049 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1053 if (filters == null || filters.isEmpty()) {
1054 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1055 if (componentsList.isRight()) {
1056 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1058 return Either.left(componentsList.left().value());
1061 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1063 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1064 if (result.isRight()) {
1065 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1066 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1068 if (result.left().value().isEmpty()) {// no assets found for requested
1070 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1072 return Either.left(result.left().value());
1075 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1076 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1077 if (assetType == ComponentTypeEnum.RESOURCE) {
1079 assetResult = getFilteredResouces(filters, inTransaction);
1081 } else if (assetType == ComponentTypeEnum.SERVICE) {
1083 assetResult = getFilteredServices(filters, inTransaction);
1088 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1090 Either<List<T>, StorageOperationStatus> components = null;
1092 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1093 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1094 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1095 if (distributionStatus != null && distEnum == null) {
1096 filters.remove(FilterKeyEnum.CATEGORY);
1097 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1100 if (categoryName != null) { // primary filter
1101 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, GraphEdgeLabels.CATEGORY.getProperty(), NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1102 if (components.isLeft() && distEnum != null) {// secondary filter
1103 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1104 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1106 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1110 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1111 distStatusSet.add(distEnum);
1112 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1113 if (servicesWithDistStatus.isRight()) { // not found == empty list
1114 return Either.left(new ArrayList<>());
1117 return Either.left((List<T>) servicesWithDistStatus.left().value());
1120 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1122 if (assetType == null || uuid == null) {
1123 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1124 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1127 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1129 if (assetTypeEnum == null) {
1130 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1131 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1134 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1136 switch (assetTypeEnum) {
1138 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1141 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1144 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1145 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1148 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1149 if (componentsListByUuid.isRight()) {
1150 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1151 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1152 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1155 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1156 return Either.left(componentsListByUuid.left().value());
1159 public List<String> getAllComponentTypesParamNames() {
1160 List<String> paramNames = new ArrayList<>();
1161 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1162 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1163 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1167 public List<String> getAllSupportedRoles() {
1168 Role[] values = Role.values();
1169 List<String> roleNames = new ArrayList<>();
1170 for (Role role : values) {
1171 roleNames.add(role.name());
1176 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1177 return elementOperation.getResourceTypesMap();
1180 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1181 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1182 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1183 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1184 return params.stream().filter(noMatch).findAny();
1187 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1188 List<String> params = new ArrayList<String>();
1189 if (1 == filters.size()) {
1190 params.add(assetType.getValue().toLowerCase());
1191 params.add(filters.keySet().iterator().next().getName());
1192 params.add(filters.values().iterator().next());
1194 params.add(assetType.getValue());
1195 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1196 params.add(filters.get(FilterKeyEnum.CATEGORY));
1201 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1203 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1204 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1205 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1206 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1207 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1209 if (categoryName != null) {
1210 subcategories = getAllSubCategories(categoryName);
1211 if (subcategories.isRight()) {
1212 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1213 return Either.right(subcategories.right().value());
1216 if (subCategoryName != null) { // primary filter
1217 if (categoryName != null) {
1218 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1219 if (!subCategoryData.isPresent()) {
1220 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1222 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction,
1223 ResourceMetadataData.class, resourceType);
1226 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1228 if (subcategories != null) {
1229 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1231 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1234 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1235 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1236 if (categoryResult.isRight()) {
1237 return Either.right(categoryResult.right().value());
1239 CategoryData categoryData = categoryResult.left().value();
1241 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1242 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1243 if (childrenNodes.isRight()) {
1244 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1246 return Either.left(childrenNodes.left().value());
1249 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1250 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1251 return childNodes.stream().filter(matchName).findAny();
1254 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1255 Class<S> clazz, ResourceTypeEnum resourceType) {
1257 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1259 if (false == inTransaction) {
1265 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1266 Class<S> clazz, ResourceTypeEnum resourceType) {
1267 List<T> components = new ArrayList<>();
1269 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1270 Map<String, Object> props = new HashMap<String, Object>();
1271 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1272 Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1273 if (getCategory.isRight()) {
1274 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1276 for (GraphNode category : getCategory.left().value()) {
1277 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1278 if (result.isRight()) {
1281 components.addAll(result.left().value());
1284 return Either.left(components);
1286 if (false == inTransaction) {
1292 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1293 List<T> components = new ArrayList<>();
1294 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1295 if (parentNodes.isLeft()) {
1296 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1297 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1298 Boolean isHighest = componentData.isHighestVersion();
1299 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1300 boolean isDeleted = componentData.isDeleted() != null && componentData.isDeleted();
1302 if (isHighest && isMatchingResourceType && !isDeleted) {
1303 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1304 if (result.isRight()) {
1305 return Either.right(result.right().value());
1307 components.add(result.left().value());
1311 return Either.left(components);
1314 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1317 if (componentType == NodeTypeEnum.Resource) {
1318 if (resourceType == null) {
1321 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1329 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1330 List<T> components = new ArrayList<>();
1332 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1333 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource,
1334 inTransaction, ResourceMetadataData.class, resourceType);
1335 if (fetched.isRight()) {
1338 components.addAll(fetched.left().value());
1340 return Either.left(components);
1343 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1344 List<Component> components = null;
1345 StorageOperationStatus status;
1346 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1347 Either<List<Component>, StorageOperationStatus> result;
1349 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1350 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1351 if (getResources.isRight()) {
1352 status = getResources.right().value();
1353 if (status != StorageOperationStatus.NOT_FOUND) {
1354 statusWrapper.setInnerElement(getResources.right().value());
1356 components = new ArrayList<>();
1359 components = getResources.left().value();
1361 if (!statusWrapper.isEmpty()) {
1362 result = Either.right(statusWrapper.getInnerElement());
1364 result = Either.left(components);
1368 if (!inTransaction) {