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.components.impl.exceptions.ComponentException;
28 import org.openecomp.sdc.be.dao.api.ActionStatus;
29 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
30 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
31 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
32 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
33 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
34 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
35 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
36 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
37 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
38 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
39 import org.openecomp.sdc.be.datatypes.enums.*;
40 import org.openecomp.sdc.be.model.*;
41 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
42 import org.openecomp.sdc.be.model.category.CategoryDefinition;
43 import org.openecomp.sdc.be.model.category.GroupingDefinition;
44 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
45 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
48 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
49 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
50 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
51 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
52 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
53 import org.openecomp.sdc.be.resources.data.category.CategoryData;
54 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
55 import org.openecomp.sdc.be.ui.model.UiCategories;
56 import org.openecomp.sdc.be.user.Role;
57 import org.openecomp.sdc.be.user.UserBusinessLogic;
58 import org.openecomp.sdc.common.datastructure.Wrapper;
59 import org.openecomp.sdc.common.log.wrappers.Logger;
60 import org.openecomp.sdc.common.util.ValidationUtils;
61 import org.openecomp.sdc.exception.ResponseFormat;
63 import java.nio.charset.StandardCharsets;
65 import java.util.function.Predicate;
66 import java.util.stream.Collectors;
68 import static org.apache.commons.lang.BooleanUtils.isTrue;
70 @org.springframework.stereotype.Component("elementsBusinessLogic")
71 public class ElementBusinessLogic extends BaseBusinessLogic {
73 private static final Logger log = Logger.getLogger(ElementBusinessLogic.class);
74 private static final String SERVICES = "services";
75 private static final String RESOURCES = "resources";
76 private static final String VALIDATION_OF_USER_FAILED_USER_ID = "Validation of user failed, userId {}";
77 private static final String COMPONENT_TYPE_IS_INVALID = "Component type {} is invalid";
78 private static final String VALIDATION_OF_USER_ROLE_FAILED_USER_ID = "Validation of user role failed, userId {}";
80 @javax.annotation.Resource
81 private IElementOperation elementOperation;
83 @javax.annotation.Resource
84 private UserBusinessLogic userAdminManager;
91 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
92 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
93 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
95 String role = user.getRole();
97 Role currentRole = Role.valueOf(role);
99 switch (currentRole) {
101 userId = user.getUserId();
102 response = handleDesigner(userId);
106 userId = user.getUserId();
107 response = handleTester();
111 userId = user.getUserId();
112 response = handleGovernor();
116 userId = user.getUserId();
117 response = handleOps();
120 case PRODUCT_STRATEGIST:
121 userId = user.getUserId();
122 response = handleProductStrategist();
125 case PRODUCT_MANAGER:
126 userId = user.getUserId();
127 response = handleProductManager(userId);
131 response = handleAdmin();
135 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
138 // 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)
139 return convertedToListResponse(response);
143 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
145 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
146 if (setResponse.isLeft()) {
147 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
148 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
150 return Either.left(arrayResponse);
152 return Either.right(setResponse.right().value());
155 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
156 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
157 // userId should stay null
158 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
159 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
160 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
161 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
165 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
166 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
167 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
168 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
169 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
170 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
171 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
172 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
173 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
175 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
176 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
180 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor() {
181 return handleFollowedCertifiedServices(null);
184 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist() {
185 // Should be empty list according to Ella, 13/03/16
186 Map<String, Set<? extends Component>> result = new HashMap<>();
187 result.put("products", new HashSet<>());
188 return Either.left(result);
191 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
192 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
193 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
194 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
195 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
196 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
197 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
198 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
199 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
201 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
202 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
206 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps() {
207 Set<DistributionStatusEnum> distStatus = new HashSet<>();
208 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
209 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
211 return handleFollowedCertifiedServices(distStatus);
214 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
216 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
217 if (services.isLeft()) {
218 Map<String, Set<? extends Component>> result = new HashMap<>();
219 Set<Service> set = new HashSet<>();
220 set.addAll(services.left().value());
221 result.put(SERVICES, set);
222 return Either.left(result);
224 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
228 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester() {
229 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
230 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
231 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
233 return getFollowedResourcesAndServices(null, lifecycleStates, null);
236 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
239 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
241 if (resources.isLeft()) {
242 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
243 if (services.isLeft()) {
244 Map<String, Set<? extends Component>> result = new HashMap<>();
245 result.put(SERVICES, services.left().value());
246 result.put(RESOURCES, resources.left().value());
247 return Either.left(result);
249 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
252 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
259 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
260 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
261 if (products.isLeft()) {
262 Map<String, Set<? extends Component>> result = new HashMap<>();
263 result.put("products", products.left().value());
264 return Either.left(result);
266 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
271 * New categories flow - start
273 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
274 return elementOperation.getAllResourceCategories();
277 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
278 return elementOperation.getAllServiceCategories();
281 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
283 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
284 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
285 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
286 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
289 Either<User, ResponseFormat> validateUser = validateUser(userId);
290 if (validateUser.isRight()) {
291 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
292 ResponseFormat responseFormat = validateUser.right().value();
294 user.setUserId(userId);
295 String currCategoryName = (category == null ? null : category.getName());
296 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
297 return Either.right(responseFormat);
300 user = validateUser.left().value();
302 if (category == null) {
303 log.debug("Category json is invalid");
304 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
305 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
306 return Either.right(responseFormat);
309 String categoryName = category.getName();
310 // For auditing of failures we need the original non-normalized name
311 String origCategoryName = categoryName;
312 if (componentTypeEnum == null) {
313 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
314 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
315 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
316 return Either.right(responseFormat);
319 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
320 if (validateUserRole.isRight()) {
321 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
322 ResponseFormat responseFormat = validateUserRole.right().value();
323 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
324 return Either.right(responseFormat);
327 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
328 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
329 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
330 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
331 return Either.right(responseFormat);
334 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
336 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
337 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
338 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
339 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
340 return Either.right(responseFormat);
343 category.setName(categoryName);
345 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
346 category.setNormalizedName(normalizedName);
348 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
350 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
351 if (categoryUniqueEither.isRight()) {
352 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
353 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
354 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
355 return Either.right(responseFormat);
358 Boolean isCategoryUnique = categoryUniqueEither.left().value();
359 if (!isCategoryUnique) {
360 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
361 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
362 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
363 return Either.right(responseFormat);
366 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
367 if (createCategoryByType.isRight()) {
368 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
369 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
370 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
371 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
373 category = createCategoryByType.left().value();
374 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
375 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
376 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
377 return Either.left(category);
380 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
382 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
383 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
384 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
385 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
387 String parentCategoryName = parentCategoryId;
389 if (subCategory == null) {
390 log.debug("Sub-category json is invalid");
391 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
392 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
393 return Either.right(responseFormat);
396 String subCategoryName = subCategory.getName();
397 // For auditing of failures we need the original non-normalized name
398 String origSubCategoryName = subCategoryName;
401 user = validateUserExists(userId, "createSubCategory", false);
402 } catch(ComponentException e){
403 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
404 ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() :
405 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
407 user.setUserId(userId);
408 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
411 if (componentTypeEnum == null) {
412 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
413 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
414 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
415 return Either.right(responseFormat);
418 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
419 if (validateComponentType.isRight()) {
420 log.debug("Validation of component type for sub-category failed");
421 ResponseFormat responseFormat = validateComponentType.right().value();
422 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
423 return Either.right(responseFormat);
426 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
427 if (validateUserRole.isRight()) {
428 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
429 ResponseFormat responseFormat = validateUserRole.right().value();
430 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
431 return Either.right(responseFormat);
434 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
435 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
437 CategoryDefinition categoryDefinition;
438 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
439 if (validateCategoryExists.isRight()) {
440 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
441 ResponseFormat responseFormat = validateCategoryExists.right().value();
442 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
443 return Either.right(responseFormat);
446 categoryDefinition = validateCategoryExists.left().value();
447 parentCategoryName = categoryDefinition.getName();
449 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
450 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
451 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
452 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
453 return Either.right(responseFormat);
456 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
458 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
459 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
460 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
461 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
462 return Either.right(responseFormat);
465 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
466 subCategory.setNormalizedName(normalizedName);
468 // Uniqueness under this category
469 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
470 if (subCategoryUniqueForCategory.isRight()) {
471 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
472 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
473 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
474 return Either.right(responseFormat);
477 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
479 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
480 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
481 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
482 return Either.right(responseFormat);
485 // Setting name of subcategory to fit the similar subcategory name
487 // For example if Network-->kUKU exists for service category Network,
488 // and user is trying to create Router-->Kuku for service category
490 // his subcategory name will be Router-->kUKU.
491 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
492 if (subCategoryUniqueForType.isRight()) {
493 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
494 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
495 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
496 return Either.right(responseFormat);
498 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
499 if (subCategoryDefinition != null) {
500 subCategoryName = subCategoryDefinition.getName();
503 subCategory.setName(subCategoryName);
504 ///////////////////////////////////////////// Validations end
506 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
507 if (createSubCategory.isRight()) {
508 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
509 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
510 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
511 return Either.right(responseFormat);
514 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
515 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
516 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
517 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
518 return Either.left(subCategoryCreated);
521 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
523 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
524 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
525 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
526 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
528 String parentCategoryName = grandParentCategoryId;
529 String parentSubCategoryName = parentSubCategoryId;
533 user = validateUserExists(userId, "create Grouping", false);
534 } catch(ComponentException e){
535 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
536 ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() :
537 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
539 user.setUserId(userId);
540 String groupingNameForAudit = grouping == null ? null : grouping.getName();
541 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
545 if (grouping == null) {
546 log.debug("Grouping json is invalid");
547 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
548 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
549 return Either.right(responseFormat);
552 String groupingName = grouping.getName();
553 // For auditing of failures we need the original non-normalized name
554 String origGroupingName = groupingName;
556 if (componentTypeEnum == null) {
557 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
558 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
559 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
560 return Either.right(responseFormat);
563 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
564 if (validateComponentType.isRight()) {
565 log.debug("Validation of component type for grouping failed");
566 ResponseFormat responseFormat = validateComponentType.right().value();
567 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
568 return Either.right(responseFormat);
571 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
572 if (validateUserRole.isRight()) {
573 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
574 ResponseFormat responseFormat = validateUserRole.right().value();
575 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
576 return Either.right(responseFormat);
579 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
580 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
581 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
584 CategoryDefinition categoryDefinition;
585 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
586 if (validateCategoryExists.isRight()) {
587 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
588 ResponseFormat responseFormat = validateCategoryExists.right().value();
589 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
590 return Either.right(responseFormat);
593 categoryDefinition = validateCategoryExists.left().value();
594 parentCategoryName = categoryDefinition.getName();
596 // Validate subcategory
597 SubCategoryDefinition subCategoryDefinition;
598 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
599 if (validateSubCategoryExists.isRight()) {
600 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
601 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
602 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
603 return Either.right(responseFormat);
606 subCategoryDefinition = validateSubCategoryExists.left().value();
607 parentSubCategoryName = subCategoryDefinition.getName();
609 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
610 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
611 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
612 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
613 return Either.right(responseFormat);
616 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
618 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
619 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
620 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
621 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
622 return Either.right(responseFormat);
625 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
626 grouping.setNormalizedName(normalizedName);
628 // Uniqueness under this category
629 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
630 if (groupingUniqueForSubCategory.isRight()) {
631 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
632 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
633 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
634 return Either.right(responseFormat);
637 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
638 if (!isGroupingUnique) {
639 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
640 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
641 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
642 return Either.right(responseFormat);
645 // Setting name of grouping to fit the similar grouping name ignoring
647 // For example if Network-->kUKU exists for service sub-category
648 // Network, and user is trying to create grouping Router-->Kuku for
649 // service sub-category Router,
650 // his grouping name will be Router-->kUKU.
651 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
652 if (groupingUniqueForType.isRight()) {
653 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
654 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
655 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
656 return Either.right(responseFormat);
658 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
659 if (groupingDefinition != null) {
660 groupingName = groupingDefinition.getName();
663 grouping.setName(groupingName);
664 ///////////////////////////////////////////// Validations end
666 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
667 if (createGrouping.isRight()) {
668 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
669 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
670 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
671 return Either.right(responseFormat);
674 GroupingDefinition groupingCreated = createGrouping.left().value();
675 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
676 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
677 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
678 return Either.left(groupingCreated);
681 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
682 ResponseFormat responseFormat;
683 User user = new User();
684 if (userId == null) {
685 user.setUserId("UNKNOWN");
686 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
687 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
688 return Either.right(responseFormat);
691 user = validateUserExists(userId, "get All Categories", false);
692 } catch (ComponentException e){
694 user.setUserId(userId);
695 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
696 responseFormat = e.getResponseFormat() != null ? e.getResponseFormat():
697 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
698 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
701 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
702 if (componentTypeEnum == null) {
703 log.debug("Cannot create category for component type {}", componentType);
704 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
705 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
706 return Either.right(responseFormat);
709 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
710 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
711 if (getAllCategoriesByType.isRight()) {
712 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
713 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
714 return Either.right(responseFormat);
716 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
717 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
718 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
719 return Either.left(categories);
722 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
723 ResponseFormat responseFormat;
724 UiCategories categories = new UiCategories();
726 User user = validateUserExists(userId, "get all categories", false);
728 // GET resource categories
729 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
730 if (getResourceCategoriesByType.isRight()) {
731 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
732 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
733 return Either.right(responseFormat);
735 categories.setResourceCategories(getResourceCategoriesByType.left().value());
737 // GET service categories
738 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
739 if (getServiceCategoriesByType.isRight()) {
740 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
741 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
742 return Either.right(responseFormat);
744 categories.setServiceCategories(getServiceCategoriesByType.left().value());
746 // GET product categories
747 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
748 if (getProductCategoriesByType.isRight()) {
749 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
750 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
751 return Either.right(responseFormat);
754 categories.setProductCategories(getProductCategoriesByType.left().value());
755 return Either.left(categories);
759 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
761 validateUserExists(userId, "delete Category", false);
763 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
764 if (componentTypeEnum == null) {
765 log.debug("Cannot create category for component type {}", componentTypeParamName);
766 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
769 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
771 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
772 if (deleteCategoryByType.isRight()) {
773 // auditing, logging here...
774 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
776 CategoryDefinition category = deleteCategoryByType.left().value();
777 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
778 return Either.left(category);
781 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String parentSubCategoryId, String componentTypeParamName, String userId) {
783 validateUserExists(userId, "delete Sub Category", false);
785 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
786 if (componentTypeEnum == null) {
787 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
788 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
791 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
793 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
794 if (deleteSubCategoryByType.isRight()) {
795 // auditing, logging here...
796 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
798 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
799 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
800 return Either.left(subCategory);
803 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String groupingId, String componentTypeParamName, String userId) {
805 validateUserExists(userId, "delete Grouping", false);
807 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
808 if (componentTypeEnum == null) {
809 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
810 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
813 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
815 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
816 if (deleteGroupingByType.isRight()) {
817 // auditing, logging here...
818 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
820 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
821 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
822 return Either.left(deletedGrouping);
825 private Either<User, ResponseFormat> validateUser(String userId) {
827 // validate user exists
828 if (userId == null) {
829 log.debug("UserId is null");
830 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
833 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
834 if (userResult.isRight()) {
835 ResponseFormat responseFormat;
836 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
837 log.debug("Not authorized user, userId = {}", userId);
838 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
840 log.debug("Failed to authorize user, userId = {}", userId);
841 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
844 return Either.right(responseFormat);
846 return Either.left(userResult.left().value());
847 // ========================================-
850 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
851 String role = user.getRole();
852 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
853 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
855 if (!(validAdminAction || validProductAction)) {
856 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
857 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
858 return Either.right(responseFormat);
860 return Either.left(true);
863 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
864 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
865 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
866 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
872 if (!(validResourceAction || validServiceAction || validProductAction)) {
873 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
874 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
875 return Either.right(responseFormat);
877 return Either.left(true);
880 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
881 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
882 if (categoryByTypeAndId.isRight()) {
883 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
884 ActionStatus actionStatus = categoryByTypeAndId.right().value();
885 ResponseFormat responseFormat;
886 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
887 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
889 responseFormat = componentsUtils.getResponseFormat(actionStatus);
891 return Either.right(responseFormat);
893 return Either.left(categoryByTypeAndId.left().value());
896 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
897 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
898 if (subCategoryByTypeAndId.isRight()) {
899 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
900 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
901 ResponseFormat responseFormat;
902 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
903 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
905 responseFormat = componentsUtils.getResponseFormat(actionStatus);
907 return Either.right(responseFormat);
909 return Either.left(subCategoryByTypeAndId.left().value());
912 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
913 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
916 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
917 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
920 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
921 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
925 * New categories flow - end
928 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
929 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
930 if (resp.isRight()) {
931 return Either.right(resp.right().value());
933 return elementOperation.getAllTags();
936 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
937 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
938 if (resp.isRight()) {
939 return Either.right(resp.right().value());
941 return elementOperation.getAllPropertyScopes();
944 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
945 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
946 if (resp.isRight()) {
947 return Either.right(resp.right().value());
949 return elementOperation.getAllArtifactTypes();
952 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
953 return elementOperation.getAllDeploymentArtifactTypes();
956 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
957 return elementOperation.getDefaultHeatTimeout();
960 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId, List<OriginTypeEnum> excludeTypes) {
962 validateUserExists(userId, "get Catalog Components", true);
963 return toscaOperationFacade.getCatalogOrArchiveComponents(true, excludeTypes)
964 .bimap(this::groupByComponentType,
965 err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
971 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
972 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
974 // fixed response for UI!!! UI need to receive always map!
976 map = new HashMap<>();
978 if (map.get(RESOURCES) == null) {
979 map.put(RESOURCES, new ArrayList());
981 if (map.get(SERVICES) == null) {
982 map.put(SERVICES, new ArrayList());
987 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
988 switch (componentTypeEnum) {
994 throw new IllegalStateException("resources or services only");
998 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
999 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1001 if (query != null) {
1002 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1003 if (invalidFilter.isPresent()) {
1004 log.debug("getFilteredAssetList: invalid filter key");
1005 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1009 if (filters == null || filters.isEmpty()) {
1010 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1011 if (componentsList.isRight()) {
1012 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1014 return Either.left(componentsList.left().value());
1017 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1019 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1020 if (result.isRight()) {
1021 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1022 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1024 if (result.left().value().isEmpty()) {// no assets found for requested
1026 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1028 return Either.left(result.left().value());
1031 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1032 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1033 if (assetType == ComponentTypeEnum.RESOURCE) {
1035 assetResult = getFilteredResouces(filters, inTransaction);
1037 } else if (assetType == ComponentTypeEnum.SERVICE) {
1039 assetResult = getFilteredServices(filters, inTransaction);
1044 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1046 Either<List<T>, StorageOperationStatus> components = null;
1048 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1049 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1050 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1051 if (distributionStatus != null && distEnum == null) {
1052 filters.remove(FilterKeyEnum.CATEGORY);
1053 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1056 if (categoryName != null) { // primary filter
1057 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1058 if (components.isLeft() && distEnum != null) {// secondary filter
1059 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1060 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1062 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1066 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1067 distStatusSet.add(distEnum);
1068 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1069 if (servicesWithDistStatus.isRight()) { // not found == empty list
1070 return Either.left(new ArrayList<>());
1073 return Either.left((List<T>) servicesWithDistStatus.left().value());
1076 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1078 if (assetType == null || uuid == null) {
1079 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1080 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1083 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1085 if (assetTypeEnum == null) {
1086 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1087 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1090 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1092 switch (assetTypeEnum) {
1094 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1097 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1100 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1101 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1104 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1105 if (componentsListByUuid.isRight()) {
1106 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1107 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1108 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1111 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1112 return Either.left(componentsListByUuid.left().value());
1115 public List<String> getAllComponentTypesParamNames() {
1116 List<String> paramNames = new ArrayList<>();
1117 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1118 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1119 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1123 public List<String> getAllSupportedRoles() {
1124 Role[] values = Role.values();
1125 List<String> roleNames = new ArrayList<>();
1126 for (Role role : values) {
1127 roleNames.add(role.name());
1132 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1133 return elementOperation.getResourceTypesMap();
1136 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1137 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1138 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1139 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1140 return params.stream().filter(noMatch).findAny();
1143 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1144 List<String> params = new ArrayList<>();
1145 if (1 == filters.size()) {
1146 params.add(assetType.getValue().toLowerCase());
1147 params.add(filters.keySet().iterator().next().getName());
1148 params.add(filters.values().iterator().next());
1150 params.add(assetType.getValue());
1151 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1152 params.add(filters.get(FilterKeyEnum.CATEGORY));
1157 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1159 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1160 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1161 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1162 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1163 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1165 if (categoryName != null) {
1166 subcategories = getAllSubCategories(categoryName);
1167 if (subcategories.isRight()) {
1168 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1169 return Either.right(subcategories.right().value());
1172 if (subCategoryName != null) { // primary filter
1173 if (categoryName != null) {
1174 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1175 if (!subCategoryData.isPresent()) {
1176 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1178 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction,
1179 ResourceMetadataData.class, resourceType);
1182 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1184 if (subcategories != null) {
1185 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1187 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1190 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1191 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1192 if (categoryResult.isRight()) {
1193 return Either.right(categoryResult.right().value());
1195 CategoryData categoryData = categoryResult.left().value();
1197 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1198 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1199 if (childrenNodes.isRight()) {
1200 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1202 return Either.left(childrenNodes.left().value());
1205 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1206 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1207 return childNodes.stream().filter(matchName).findAny();
1210 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1211 Class<S> clazz, ResourceTypeEnum resourceType) {
1213 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1215 if (!inTransaction) {
1221 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1222 Class<S> clazz, ResourceTypeEnum resourceType) {
1223 List<T> components = new ArrayList<>();
1225 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1226 Map<String, Object> props = new HashMap<>();
1227 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1228 Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1229 if (getCategory.isRight()) {
1230 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1232 for (GraphNode category : getCategory.left().value()) {
1233 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1234 if (result.isRight()) {
1237 components.addAll(result.left().value());
1240 return Either.left(components);
1242 if (!inTransaction) {
1249 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1250 List<T> components = new ArrayList<>();
1251 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1252 if (parentNodes.isLeft()) {
1253 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1254 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1255 Boolean isHighest = componentData.isHighestVersion();
1256 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1257 boolean isDeleted = isTrue(componentData.isDeleted());
1258 boolean isArchived = isTrue(componentData.isArchived());
1260 if (isHighest && isMatchingResourceType && !isDeleted && !isArchived) {
1261 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1262 if (result.isRight()) {
1263 return Either.right(result.right().value());
1265 components.add(result.left().value());
1269 return Either.left(components);
1272 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1275 if (componentType == NodeTypeEnum.Resource) {
1276 if (resourceType == null) {
1279 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1287 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1288 List<T> components = new ArrayList<>();
1290 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1291 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource,
1292 inTransaction, ResourceMetadataData.class, resourceType);
1293 if (fetched.isRight()) {
1296 components.addAll(fetched.left().value());
1298 return Either.left(components);
1301 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1302 List<Component> components = null;
1303 StorageOperationStatus status;
1304 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1305 Either<List<Component>, StorageOperationStatus> result;
1307 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1308 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1309 if (getResources.isRight()) {
1310 status = getResources.right().value();
1311 if (status != StorageOperationStatus.NOT_FOUND) {
1312 statusWrapper.setInnerElement(getResources.right().value());
1314 components = new ArrayList<>();
1317 components = getResources.left().value();
1319 if (!statusWrapper.isEmpty()) {
1320 result = Either.right(statusWrapper.getInnerElement());
1322 result = Either.left(components);
1326 if (!inTransaction) {