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();
96 String userId = user.getUserId();
97 Role currentRole = Role.valueOf(role);
99 switch (currentRole) {
101 response = handleDesigner(userId);
105 response = handleTester();
109 response = handleGovernor();
113 response = handleOps();
116 case PRODUCT_STRATEGIST:
117 response = handleProductStrategist();
120 case PRODUCT_MANAGER:
121 response = handleProductManager(userId);
125 response = handleAdmin();
129 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
132 // 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)
133 return convertedToListResponse(response);
137 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
139 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
140 if (setResponse.isLeft()) {
141 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
142 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
144 return Either.left(arrayResponse);
146 return Either.right(setResponse.right().value());
149 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
150 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
151 // userId should stay null
152 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
153 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
154 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
155 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
159 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
160 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
161 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
162 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
163 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
164 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
165 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
166 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
167 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
169 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
170 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
174 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor() {
175 return handleFollowedCertifiedServices(null);
178 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist() {
179 // Should be empty list according to Ella, 13/03/16
180 Map<String, Set<? extends Component>> result = new HashMap<>();
181 result.put("products", new HashSet<>());
182 return Either.left(result);
185 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
186 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
187 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
188 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
189 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
190 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
191 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
192 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
193 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
195 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
196 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
200 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps() {
201 Set<DistributionStatusEnum> distStatus = new HashSet<>();
202 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
203 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
205 return handleFollowedCertifiedServices(distStatus);
208 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
210 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
211 if (services.isLeft()) {
212 Map<String, Set<? extends Component>> result = new HashMap<>();
213 Set<Service> set = new HashSet<>();
214 set.addAll(services.left().value());
215 result.put(SERVICES, set);
216 return Either.left(result);
218 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
222 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester() {
223 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
224 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
225 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
227 return getFollowedResourcesAndServices(null, lifecycleStates, null);
230 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
233 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
235 if (resources.isLeft()) {
236 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
237 if (services.isLeft()) {
238 Map<String, Set<? extends Component>> result = new HashMap<>();
239 result.put(SERVICES, services.left().value());
240 result.put(RESOURCES, resources.left().value());
241 return Either.left(result);
243 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
246 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
253 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
254 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
255 if (products.isLeft()) {
256 Map<String, Set<? extends Component>> result = new HashMap<>();
257 result.put("products", products.left().value());
258 return Either.left(result);
260 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
265 * New categories flow - start
267 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
268 return elementOperation.getAllResourceCategories();
271 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
272 return elementOperation.getAllServiceCategories();
275 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
277 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
278 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
279 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
280 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
283 Either<User, ResponseFormat> validateUser = validateUser(userId);
284 if (validateUser.isRight()) {
285 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
286 ResponseFormat responseFormat = validateUser.right().value();
288 user.setUserId(userId);
289 String currCategoryName = (category == null ? null : category.getName());
290 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
291 return Either.right(responseFormat);
294 user = validateUser.left().value();
296 if (category == null) {
297 log.debug("Category json is invalid");
298 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
299 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
300 return Either.right(responseFormat);
303 String categoryName = category.getName();
304 // For auditing of failures we need the original non-normalized name
305 String origCategoryName = categoryName;
306 if (componentTypeEnum == null) {
307 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
308 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
309 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
310 return Either.right(responseFormat);
313 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
314 if (validateUserRole.isRight()) {
315 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
316 ResponseFormat responseFormat = validateUserRole.right().value();
317 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
318 return Either.right(responseFormat);
321 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
322 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
323 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
324 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
325 return Either.right(responseFormat);
328 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
330 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
331 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
332 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
333 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
334 return Either.right(responseFormat);
337 category.setName(categoryName);
339 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
340 category.setNormalizedName(normalizedName);
342 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
344 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
345 if (categoryUniqueEither.isRight()) {
346 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
347 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
348 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
349 return Either.right(responseFormat);
352 Boolean isCategoryUnique = categoryUniqueEither.left().value();
353 if (!isCategoryUnique) {
354 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
355 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
356 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
357 return Either.right(responseFormat);
360 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
361 if (createCategoryByType.isRight()) {
362 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
363 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
364 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
365 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
367 category = createCategoryByType.left().value();
368 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
369 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
370 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
371 return Either.left(category);
374 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
376 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
377 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
378 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
379 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
381 String parentCategoryName = parentCategoryId;
383 if (subCategory == null) {
384 log.debug("Sub-category json is invalid");
385 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
386 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
387 return Either.right(responseFormat);
390 String subCategoryName = subCategory.getName();
391 // For auditing of failures we need the original non-normalized name
392 String origSubCategoryName = subCategoryName;
395 user = validateUserExists(userId, "createSubCategory", false);
396 } catch(ComponentException e){
397 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
398 ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() :
399 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
401 user.setUserId(userId);
402 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
405 if (componentTypeEnum == null) {
406 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
407 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
408 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
409 return Either.right(responseFormat);
412 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
413 if (validateComponentType.isRight()) {
414 log.debug("Validation of component type for sub-category failed");
415 ResponseFormat responseFormat = validateComponentType.right().value();
416 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
417 return Either.right(responseFormat);
420 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
421 if (validateUserRole.isRight()) {
422 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
423 ResponseFormat responseFormat = validateUserRole.right().value();
424 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
425 return Either.right(responseFormat);
428 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
429 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
431 CategoryDefinition categoryDefinition;
432 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
433 if (validateCategoryExists.isRight()) {
434 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
435 ResponseFormat responseFormat = validateCategoryExists.right().value();
436 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
437 return Either.right(responseFormat);
440 categoryDefinition = validateCategoryExists.left().value();
441 parentCategoryName = categoryDefinition.getName();
443 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
444 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
445 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
446 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
447 return Either.right(responseFormat);
450 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
452 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
453 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
454 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
455 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
456 return Either.right(responseFormat);
459 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
460 subCategory.setNormalizedName(normalizedName);
462 // Uniqueness under this category
463 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
464 if (subCategoryUniqueForCategory.isRight()) {
465 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
466 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
467 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
468 return Either.right(responseFormat);
471 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
473 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
474 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
475 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
476 return Either.right(responseFormat);
479 // Setting name of subcategory to fit the similar subcategory name
481 // For example if Network-->kUKU exists for service category Network,
482 // and user is trying to create Router-->Kuku for service category
484 // his subcategory name will be Router-->kUKU.
485 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
486 if (subCategoryUniqueForType.isRight()) {
487 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
488 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
489 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
490 return Either.right(responseFormat);
492 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
493 if (subCategoryDefinition != null) {
494 subCategoryName = subCategoryDefinition.getName();
497 subCategory.setName(subCategoryName);
498 ///////////////////////////////////////////// Validations end
500 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
501 if (createSubCategory.isRight()) {
502 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
503 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
504 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
505 return Either.right(responseFormat);
508 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
509 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
510 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
511 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
512 return Either.left(subCategoryCreated);
515 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
517 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
518 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
519 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
520 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
522 String parentCategoryName = grandParentCategoryId;
523 String parentSubCategoryName = parentSubCategoryId;
527 user = validateUserExists(userId, "create Grouping", false);
528 } catch(ComponentException e){
529 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
530 ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() :
531 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
533 user.setUserId(userId);
534 String groupingNameForAudit = grouping == null ? null : grouping.getName();
535 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
539 if (grouping == null) {
540 log.debug("Grouping json is invalid");
541 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
542 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
543 return Either.right(responseFormat);
546 String groupingName = grouping.getName();
547 // For auditing of failures we need the original non-normalized name
548 String origGroupingName = groupingName;
550 if (componentTypeEnum == null) {
551 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
552 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
553 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
554 return Either.right(responseFormat);
557 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
558 if (validateComponentType.isRight()) {
559 log.debug("Validation of component type for grouping failed");
560 ResponseFormat responseFormat = validateComponentType.right().value();
561 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
562 return Either.right(responseFormat);
565 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
566 if (validateUserRole.isRight()) {
567 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
568 ResponseFormat responseFormat = validateUserRole.right().value();
569 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
570 return Either.right(responseFormat);
573 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
574 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
575 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
578 CategoryDefinition categoryDefinition;
579 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
580 if (validateCategoryExists.isRight()) {
581 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
582 ResponseFormat responseFormat = validateCategoryExists.right().value();
583 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
584 return Either.right(responseFormat);
587 categoryDefinition = validateCategoryExists.left().value();
588 parentCategoryName = categoryDefinition.getName();
590 // Validate subcategory
591 SubCategoryDefinition subCategoryDefinition;
592 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
593 if (validateSubCategoryExists.isRight()) {
594 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
595 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
596 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
597 return Either.right(responseFormat);
600 subCategoryDefinition = validateSubCategoryExists.left().value();
601 parentSubCategoryName = subCategoryDefinition.getName();
603 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
604 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
605 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
606 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
607 return Either.right(responseFormat);
610 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
612 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
613 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
614 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
615 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
616 return Either.right(responseFormat);
619 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
620 grouping.setNormalizedName(normalizedName);
622 // Uniqueness under this category
623 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
624 if (groupingUniqueForSubCategory.isRight()) {
625 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
626 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
627 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
628 return Either.right(responseFormat);
631 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
632 if (!isGroupingUnique) {
633 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
634 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
635 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
636 return Either.right(responseFormat);
639 // Setting name of grouping to fit the similar grouping name ignoring
641 // For example if Network-->kUKU exists for service sub-category
642 // Network, and user is trying to create grouping Router-->Kuku for
643 // service sub-category Router,
644 // his grouping name will be Router-->kUKU.
645 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
646 if (groupingUniqueForType.isRight()) {
647 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
648 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
649 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
650 return Either.right(responseFormat);
652 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
653 if (groupingDefinition != null) {
654 groupingName = groupingDefinition.getName();
657 grouping.setName(groupingName);
658 ///////////////////////////////////////////// Validations end
660 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
661 if (createGrouping.isRight()) {
662 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
663 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
664 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
665 return Either.right(responseFormat);
668 GroupingDefinition groupingCreated = createGrouping.left().value();
669 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
670 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
671 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
672 return Either.left(groupingCreated);
675 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
676 ResponseFormat responseFormat;
677 User user = new User();
678 if (userId == null) {
679 user.setUserId("UNKNOWN");
680 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
681 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
682 return Either.right(responseFormat);
685 user = validateUserExists(userId, "get All Categories", false);
686 } catch (ComponentException e){
688 user.setUserId(userId);
689 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
690 responseFormat = e.getResponseFormat() != null ? e.getResponseFormat():
691 componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
692 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
695 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
696 if (componentTypeEnum == null) {
697 log.debug("Cannot create category for component type {}", componentType);
698 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
699 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
700 return Either.right(responseFormat);
703 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
704 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
705 if (getAllCategoriesByType.isRight()) {
706 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
707 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
708 return Either.right(responseFormat);
710 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
711 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
712 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
713 return Either.left(categories);
716 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
717 ResponseFormat responseFormat;
718 UiCategories categories = new UiCategories();
720 User user = validateUserExists(userId, "get all categories", false);
722 // GET resource categories
723 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
724 if (getResourceCategoriesByType.isRight()) {
725 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
726 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
727 return Either.right(responseFormat);
729 categories.setResourceCategories(getResourceCategoriesByType.left().value());
731 // GET service categories
732 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
733 if (getServiceCategoriesByType.isRight()) {
734 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
735 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
736 return Either.right(responseFormat);
738 categories.setServiceCategories(getServiceCategoriesByType.left().value());
740 // GET product categories
741 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
742 if (getProductCategoriesByType.isRight()) {
743 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
744 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
745 return Either.right(responseFormat);
748 categories.setProductCategories(getProductCategoriesByType.left().value());
749 return Either.left(categories);
753 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
755 validateUserExists(userId, "delete Category", false);
757 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
758 if (componentTypeEnum == null) {
759 log.debug("Cannot create category for component type {}", componentTypeParamName);
760 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
763 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
765 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
766 if (deleteCategoryByType.isRight()) {
767 // auditing, logging here...
768 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
770 CategoryDefinition category = deleteCategoryByType.left().value();
771 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
772 return Either.left(category);
775 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String parentSubCategoryId, String componentTypeParamName, String userId) {
777 validateUserExists(userId, "delete Sub Category", false);
779 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
780 if (componentTypeEnum == null) {
781 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
782 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
785 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
787 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
788 if (deleteSubCategoryByType.isRight()) {
789 // auditing, logging here...
790 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
792 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
793 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
794 return Either.left(subCategory);
797 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String groupingId, String componentTypeParamName, String userId) {
799 validateUserExists(userId, "delete Grouping", false);
801 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
802 if (componentTypeEnum == null) {
803 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
804 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
807 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
809 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
810 if (deleteGroupingByType.isRight()) {
811 // auditing, logging here...
812 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
814 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
815 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
816 return Either.left(deletedGrouping);
819 private Either<User, ResponseFormat> validateUser(String userId) {
821 // validate user exists
822 if (userId == null) {
823 log.debug("UserId is null");
824 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
827 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
828 if (userResult.isRight()) {
829 ResponseFormat responseFormat;
830 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
831 log.debug("Not authorized user, userId = {}", userId);
832 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
834 log.debug("Failed to authorize user, userId = {}", userId);
835 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
838 return Either.right(responseFormat);
840 return Either.left(userResult.left().value());
841 // ========================================-
844 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
845 String role = user.getRole();
846 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
847 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
849 if (!(validAdminAction || validProductAction)) {
850 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
851 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
852 return Either.right(responseFormat);
854 return Either.left(true);
857 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
858 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
859 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
860 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
866 if (!(validResourceAction || validServiceAction || validProductAction)) {
867 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
868 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
869 return Either.right(responseFormat);
871 return Either.left(true);
874 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
875 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
876 if (categoryByTypeAndId.isRight()) {
877 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
878 ActionStatus actionStatus = categoryByTypeAndId.right().value();
879 ResponseFormat responseFormat;
880 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
881 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
883 responseFormat = componentsUtils.getResponseFormat(actionStatus);
885 return Either.right(responseFormat);
887 return Either.left(categoryByTypeAndId.left().value());
890 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
891 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
892 if (subCategoryByTypeAndId.isRight()) {
893 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
894 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
895 ResponseFormat responseFormat;
896 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
897 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
899 responseFormat = componentsUtils.getResponseFormat(actionStatus);
901 return Either.right(responseFormat);
903 return Either.left(subCategoryByTypeAndId.left().value());
906 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
907 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
910 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
911 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
914 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
915 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
919 * New categories flow - end
922 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
923 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
924 if (resp.isRight()) {
925 return Either.right(resp.right().value());
927 return elementOperation.getAllTags();
930 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
931 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
932 if (resp.isRight()) {
933 return Either.right(resp.right().value());
935 return elementOperation.getAllPropertyScopes();
938 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
939 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
940 if (resp.isRight()) {
941 return Either.right(resp.right().value());
943 return elementOperation.getAllArtifactTypes();
946 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
947 return elementOperation.getAllDeploymentArtifactTypes();
950 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
951 return elementOperation.getDefaultHeatTimeout();
954 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId, List<OriginTypeEnum> excludeTypes) {
956 validateUserExists(userId, "get Catalog Components", true);
957 return toscaOperationFacade.getCatalogOrArchiveComponents(true, excludeTypes)
958 .bimap(this::groupByComponentType,
959 err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
965 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
966 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
968 // fixed response for UI!!! UI need to receive always map!
970 map = new HashMap<>();
972 if (map.get(RESOURCES) == null) {
973 map.put(RESOURCES, new ArrayList());
975 if (map.get(SERVICES) == null) {
976 map.put(SERVICES, new ArrayList());
981 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
982 switch (componentTypeEnum) {
988 throw new IllegalStateException("resources or services only");
992 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
993 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
996 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
997 if (invalidFilter.isPresent()) {
998 log.debug("getFilteredAssetList: invalid filter key");
999 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1003 if (filters == null || filters.isEmpty()) {
1004 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1005 if (componentsList.isRight()) {
1006 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1008 return Either.left(componentsList.left().value());
1011 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1013 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1014 if (result.isRight()) {
1015 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1016 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1018 if (result.left().value().isEmpty()) {// no assets found for requested
1020 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1022 return Either.left(result.left().value());
1025 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1026 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1027 if (assetType == ComponentTypeEnum.RESOURCE) {
1029 assetResult = getFilteredResouces(filters, inTransaction);
1031 } else if (assetType == ComponentTypeEnum.SERVICE) {
1033 assetResult = getFilteredServices(filters, inTransaction);
1038 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1040 Either<List<T>, StorageOperationStatus> components = null;
1042 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1043 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1044 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1045 if (distributionStatus != null && distEnum == null) {
1046 filters.remove(FilterKeyEnum.CATEGORY);
1047 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1050 if (categoryName != null) { // primary filter
1051 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1052 if (components.isLeft() && distEnum != null) {// secondary filter
1053 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1054 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1056 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1060 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1061 distStatusSet.add(distEnum);
1062 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1063 if (servicesWithDistStatus.isRight()) { // not found == empty list
1064 return Either.left(new ArrayList<>());
1067 return Either.left((List<T>) servicesWithDistStatus.left().value());
1070 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1072 if (assetType == null || uuid == null) {
1073 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1074 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1077 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1079 if (assetTypeEnum == null) {
1080 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1081 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1084 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1086 switch (assetTypeEnum) {
1088 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1091 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1094 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1095 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1098 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1099 if (componentsListByUuid.isRight()) {
1100 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1101 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1102 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1105 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1106 return Either.left(componentsListByUuid.left().value());
1109 public List<String> getAllComponentTypesParamNames() {
1110 List<String> paramNames = new ArrayList<>();
1111 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1112 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1113 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1117 public List<String> getAllSupportedRoles() {
1118 Role[] values = Role.values();
1119 List<String> roleNames = new ArrayList<>();
1120 for (Role role : values) {
1121 roleNames.add(role.name());
1126 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1127 return elementOperation.getResourceTypesMap();
1130 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1131 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1132 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1133 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1134 return params.stream().filter(noMatch).findAny();
1137 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1138 List<String> params = new ArrayList<>();
1139 if (1 == filters.size()) {
1140 params.add(assetType.getValue().toLowerCase());
1141 params.add(filters.keySet().iterator().next().getName());
1142 params.add(filters.values().iterator().next());
1144 params.add(assetType.getValue());
1145 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1146 params.add(filters.get(FilterKeyEnum.CATEGORY));
1151 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1153 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1154 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1155 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1156 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1157 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1159 if (categoryName != null) {
1160 subcategories = getAllSubCategories(categoryName);
1161 if (subcategories.isRight()) {
1162 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1163 return Either.right(subcategories.right().value());
1166 if (subCategoryName != null) { // primary filter
1167 if (categoryName != null) {
1168 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1169 if (!subCategoryData.isPresent()) {
1170 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1172 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction,
1173 ResourceMetadataData.class, resourceType);
1176 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1178 if (subcategories != null) {
1179 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1181 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1184 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1185 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1186 if (categoryResult.isRight()) {
1187 return Either.right(categoryResult.right().value());
1189 CategoryData categoryData = categoryResult.left().value();
1191 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1192 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1193 if (childrenNodes.isRight()) {
1194 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1196 return Either.left(childrenNodes.left().value());
1199 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1200 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1201 return childNodes.stream().filter(matchName).findAny();
1204 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1205 Class<S> clazz, ResourceTypeEnum resourceType) {
1207 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1209 if (!inTransaction) {
1215 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1216 Class<S> clazz, ResourceTypeEnum resourceType) {
1217 List<T> components = new ArrayList<>();
1219 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1220 Map<String, Object> props = new HashMap<>();
1221 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1222 Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1223 if (getCategory.isRight()) {
1224 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1226 for (GraphNode category : getCategory.left().value()) {
1227 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1228 if (result.isRight()) {
1231 components.addAll(result.left().value());
1234 return Either.left(components);
1236 if (!inTransaction) {
1243 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1244 List<T> components = new ArrayList<>();
1245 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1246 if (parentNodes.isLeft()) {
1247 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1248 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1249 Boolean isHighest = componentData.isHighestVersion();
1250 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1251 boolean isDeleted = isTrue(componentData.isDeleted());
1252 boolean isArchived = isTrue(componentData.isArchived());
1254 if (isHighest && isMatchingResourceType && !isDeleted && !isArchived) {
1255 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1256 if (result.isRight()) {
1257 return Either.right(result.right().value());
1259 components.add(result.left().value());
1263 return Either.left(components);
1266 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1269 if (componentType == NodeTypeEnum.Resource) {
1270 if (resourceType == null) {
1273 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1281 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1282 List<T> components = new ArrayList<>();
1284 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1285 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource,
1286 inTransaction, ResourceMetadataData.class, resourceType);
1287 if (fetched.isRight()) {
1290 components.addAll(fetched.left().value());
1292 return Either.left(components);
1295 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1296 List<Component> components = null;
1297 StorageOperationStatus status;
1298 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1299 Either<List<Component>, StorageOperationStatus> result;
1301 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1302 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1303 if (getResources.isRight()) {
1304 status = getResources.right().value();
1305 if (status != StorageOperationStatus.NOT_FOUND) {
1306 statusWrapper.setInnerElement(getResources.right().value());
1308 components = new ArrayList<>();
1311 components = getResources.left().value();
1313 if (!statusWrapper.isEmpty()) {
1314 result = Either.right(statusWrapper.getInnerElement());
1316 result = Either.left(components);
1320 if (!inTransaction) {