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=========================================================
19 * Modifications copyright (c) 2019 Nokia
20 * ================================================================================
23 package org.openecomp.sdc.be.components.impl;
25 import fj.data.Either;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.http.NameValuePair;
28 import org.apache.http.client.utils.URLEncodedUtils;
29 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
30 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
31 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
34 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
35 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
36 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
37 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
38 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
39 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
40 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
41 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
42 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
43 import org.openecomp.sdc.be.datatypes.enums.*;
44 import org.openecomp.sdc.be.model.*;
45 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
46 import org.openecomp.sdc.be.model.category.CategoryDefinition;
47 import org.openecomp.sdc.be.model.category.GroupingDefinition;
48 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
49 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
50 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
51 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
52 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
53 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
54 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
55 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
56 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
57 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
58 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
59 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
60 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
61 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
62 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
63 import org.openecomp.sdc.be.resources.data.category.CategoryData;
64 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
65 import org.openecomp.sdc.be.ui.model.UiCategories;
66 import org.openecomp.sdc.be.user.Role;
67 import org.openecomp.sdc.be.user.UserBusinessLogic;
68 import org.openecomp.sdc.common.datastructure.Wrapper;
69 import org.openecomp.sdc.common.log.wrappers.Logger;
70 import org.openecomp.sdc.common.util.ValidationUtils;
71 import org.openecomp.sdc.exception.ResponseFormat;
73 import java.nio.charset.StandardCharsets;
75 import java.util.function.Predicate;
76 import java.util.stream.Collectors;
77 import org.springframework.beans.factory.annotation.Autowired;
79 import static org.apache.commons.lang.BooleanUtils.isTrue;
81 @org.springframework.stereotype.Component("elementsBusinessLogic")
82 public class ElementBusinessLogic extends BaseBusinessLogic {
84 private static final Logger log = Logger.getLogger(ElementBusinessLogic.class);
85 private static final String SERVICES = "services";
86 private static final String RESOURCES = "resources";
87 private static final String VALIDATION_OF_USER_FAILED_USER_ID = "Validation of user failed, userId {}";
88 private static final String COMPONENT_TYPE_IS_INVALID = "Component type {} is invalid";
89 private static final String VALIDATION_OF_USER_ROLE_FAILED_USER_ID = "Validation of user role failed, userId {}";
91 private final IElementOperation elementOperation;
92 private final UserBusinessLogic userAdminManager;
95 public ElementBusinessLogic(IElementOperation elementDao,
96 IGroupOperation groupOperation,
97 IGroupInstanceOperation groupInstanceOperation,
98 IGroupTypeOperation groupTypeOperation,
99 GroupBusinessLogic groupBusinessLogic,
100 InterfaceOperation interfaceOperation,
101 InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
102 ArtifactsOperations artifactToscaOperation, IElementOperation elementOperation,
103 UserBusinessLogic userAdminManager) {
104 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation,
105 interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
106 this.elementOperation = elementOperation;
107 this.userAdminManager = userAdminManager;
115 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
116 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
117 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
119 String role = user.getRole();
120 String userId = user.getUserId();
121 Role currentRole = Role.valueOf(role);
123 switch (currentRole) {
125 response = handleDesigner(userId);
129 response = handleTester();
133 response = handleGovernor();
137 response = handleOps();
140 case PRODUCT_STRATEGIST:
141 response = handleProductStrategist();
144 case PRODUCT_MANAGER:
145 response = handleProductManager(userId);
149 response = handleAdmin();
153 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
156 // 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)
157 return convertedToListResponse(response);
161 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
163 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
164 if (setResponse.isLeft()) {
165 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
166 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
168 return Either.left(arrayResponse);
170 return Either.right(setResponse.right().value());
173 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
174 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
175 // userId should stay null
176 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
177 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
178 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
179 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
183 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
184 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
185 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
186 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
187 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
188 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
189 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
190 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
191 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
193 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
194 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
198 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor() {
199 return handleFollowedCertifiedServices(null);
202 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist() {
203 // Should be empty list according to Ella, 13/03/16
204 Map<String, Set<? extends Component>> result = new HashMap<>();
205 result.put("products", new HashSet<>());
206 return Either.left(result);
209 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
210 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
211 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
212 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
213 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
214 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
215 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
216 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
217 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
219 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
220 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
224 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps() {
225 Set<DistributionStatusEnum> distStatus = new HashSet<>();
226 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
227 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
229 return handleFollowedCertifiedServices(distStatus);
232 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
234 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
235 if (services.isLeft()) {
236 Map<String, Set<? extends Component>> result = new HashMap<>();
237 Set<Service> set = new HashSet<>();
238 set.addAll(services.left().value());
239 result.put(SERVICES, set);
240 return Either.left(result);
242 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
246 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester() {
247 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
248 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
249 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
251 return getFollowedResourcesAndServices(null, lifecycleStates, null);
254 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
257 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
259 if (resources.isLeft()) {
260 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
261 if (services.isLeft()) {
262 Map<String, Set<? extends Component>> result = new HashMap<>();
263 result.put(SERVICES, services.left().value());
264 result.put(RESOURCES, resources.left().value());
265 return Either.left(result);
267 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
270 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
273 janusGraphDao.commit();
277 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
278 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
279 if (products.isLeft()) {
280 Map<String, Set<? extends Component>> result = new HashMap<>();
281 result.put("products", products.left().value());
282 return Either.left(result);
284 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
289 * New categories flow - start
291 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
292 return elementOperation.getAllResourceCategories();
295 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
296 return elementOperation.getAllServiceCategories();
299 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
301 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
302 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
303 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
304 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
307 Either<User, ResponseFormat> validateUser = validateUser(userId);
308 if (validateUser.isRight()) {
309 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
310 ResponseFormat responseFormat = validateUser.right().value();
312 user.setUserId(userId);
313 String currCategoryName = (category == null ? null : category.getName());
314 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
315 return Either.right(responseFormat);
318 user = validateUser.left().value();
320 if (category == null) {
321 log.debug("Category json is invalid");
322 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
323 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
324 return Either.right(responseFormat);
327 String categoryName = category.getName();
328 // For auditing of failures we need the original non-normalized name
329 String origCategoryName = categoryName;
330 if (componentTypeEnum == null) {
331 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
332 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
333 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
334 return Either.right(responseFormat);
337 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
338 if (validateUserRole.isRight()) {
339 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
340 ResponseFormat responseFormat = validateUserRole.right().value();
341 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
342 return Either.right(responseFormat);
345 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
346 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
347 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
348 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
349 return Either.right(responseFormat);
352 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
354 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
355 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
356 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
357 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
358 return Either.right(responseFormat);
361 category.setName(categoryName);
363 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
364 category.setNormalizedName(normalizedName);
366 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
368 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
369 if (categoryUniqueEither.isRight()) {
370 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
371 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
372 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
373 return Either.right(responseFormat);
376 Boolean isCategoryUnique = categoryUniqueEither.left().value();
377 if (!isCategoryUnique) {
378 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
379 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
380 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
381 return Either.right(responseFormat);
384 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
385 if (createCategoryByType.isRight()) {
386 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
387 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
388 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
389 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
391 category = createCategoryByType.left().value();
392 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
393 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
394 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
395 return Either.left(category);
398 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
400 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
401 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
402 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
403 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
405 String parentCategoryName = parentCategoryId;
407 if (subCategory == null) {
408 log.debug("Sub-category json is invalid");
409 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
410 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
411 return Either.right(responseFormat);
414 String subCategoryName = subCategory.getName();
415 // For auditing of failures we need the original non-normalized name
416 String origSubCategoryName = subCategoryName;
419 user = validateUserExists(userId, "createSubCategory", false);
420 } catch(ByActionStatusComponentException e){
421 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
422 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName,
425 } catch(ByResponseFormatComponentException e){
426 ResponseFormat responseFormat = e.getResponseFormat();
427 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName,
431 if (componentTypeEnum == null) {
432 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
433 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
434 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
435 return Either.right(responseFormat);
438 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
439 if (validateComponentType.isRight()) {
440 log.debug("Validation of component type for sub-category failed");
441 ResponseFormat responseFormat = validateComponentType.right().value();
442 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
443 return Either.right(responseFormat);
446 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
447 if (validateUserRole.isRight()) {
448 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
449 ResponseFormat responseFormat = validateUserRole.right().value();
450 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
451 return Either.right(responseFormat);
454 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
455 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
457 CategoryDefinition categoryDefinition;
458 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
459 if (validateCategoryExists.isRight()) {
460 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
461 ResponseFormat responseFormat = validateCategoryExists.right().value();
462 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
463 return Either.right(responseFormat);
466 categoryDefinition = validateCategoryExists.left().value();
467 parentCategoryName = categoryDefinition.getName();
469 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
470 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
471 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
472 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
473 return Either.right(responseFormat);
476 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
478 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
479 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
480 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
481 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
482 return Either.right(responseFormat);
485 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
486 subCategory.setNormalizedName(normalizedName);
488 // Uniqueness under this category
489 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
490 if (subCategoryUniqueForCategory.isRight()) {
491 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
492 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
493 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
494 return Either.right(responseFormat);
497 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
499 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
500 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
501 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
502 return Either.right(responseFormat);
505 // Setting name of subcategory to fit the similar subcategory name
507 // For example if Network-->kUKU exists for service category Network,
508 // and user is trying to create Router-->Kuku for service category
510 // his subcategory name will be Router-->kUKU.
511 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
512 if (subCategoryUniqueForType.isRight()) {
513 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
514 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
515 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
516 return Either.right(responseFormat);
518 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
519 if (subCategoryDefinition != null) {
520 subCategoryName = subCategoryDefinition.getName();
523 subCategory.setName(subCategoryName);
524 ///////////////////////////////////////////// Validations end
526 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
527 if (createSubCategory.isRight()) {
528 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
529 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
530 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
531 return Either.right(responseFormat);
534 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
535 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
536 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
537 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
538 return Either.left(subCategoryCreated);
541 private void handleComponentException(String userId, AuditingActionEnum auditingAction, String componentType,
542 String parentCategoryName, String origSubCategoryName, ResponseFormat responseFormat) {
544 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
546 user.setUserId(userId);
547 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction,
551 private void handleComponentException(GroupingDefinition grouping, String userId, AuditingActionEnum auditingAction,
552 String componentType, String parentCategoryName, String parentSubCategoryName, ResponseFormat responseFormat) {
554 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
556 user.setUserId(userId);
557 String groupingNameForAudit = grouping == null ? null : grouping.getName();
558 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit,
559 auditingAction, componentType);
562 private void handleComponentException(String componentType, String userId, ResponseFormat responseFormat) {
565 user.setUserId(userId);
566 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
567 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
570 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
572 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
573 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
574 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
575 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
577 String parentCategoryName = grandParentCategoryId;
578 String parentSubCategoryName = parentSubCategoryId;
582 user = validateUserExists(userId, "create Grouping", false);
583 } catch(ByResponseFormatComponentException e){
584 ResponseFormat responseFormat = e.getResponseFormat();
585 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName,
586 parentSubCategoryName,
589 } catch(ByActionStatusComponentException e){
590 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
591 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName,
592 parentSubCategoryName, responseFormat);
596 if (grouping == null) {
597 log.debug("Grouping json is invalid");
598 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
599 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
600 return Either.right(responseFormat);
603 String groupingName = grouping.getName();
604 // For auditing of failures we need the original non-normalized name
605 String origGroupingName = groupingName;
607 if (componentTypeEnum == null) {
608 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
609 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
610 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
611 return Either.right(responseFormat);
614 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
615 if (validateComponentType.isRight()) {
616 log.debug("Validation of component type for grouping failed");
617 ResponseFormat responseFormat = validateComponentType.right().value();
618 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
619 return Either.right(responseFormat);
622 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
623 if (validateUserRole.isRight()) {
624 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
625 ResponseFormat responseFormat = validateUserRole.right().value();
626 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
627 return Either.right(responseFormat);
630 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
631 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
632 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
635 CategoryDefinition categoryDefinition;
636 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
637 if (validateCategoryExists.isRight()) {
638 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
639 ResponseFormat responseFormat = validateCategoryExists.right().value();
640 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
641 return Either.right(responseFormat);
644 categoryDefinition = validateCategoryExists.left().value();
645 parentCategoryName = categoryDefinition.getName();
647 // Validate subcategory
648 SubCategoryDefinition subCategoryDefinition;
649 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
650 if (validateSubCategoryExists.isRight()) {
651 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
652 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
653 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
654 return Either.right(responseFormat);
657 subCategoryDefinition = validateSubCategoryExists.left().value();
658 parentSubCategoryName = subCategoryDefinition.getName();
660 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
661 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
662 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
663 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
664 return Either.right(responseFormat);
667 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
669 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
670 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
671 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
672 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
673 return Either.right(responseFormat);
676 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
677 grouping.setNormalizedName(normalizedName);
679 // Uniqueness under this category
680 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
681 if (groupingUniqueForSubCategory.isRight()) {
682 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
683 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
684 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
685 return Either.right(responseFormat);
688 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
689 if (!isGroupingUnique) {
690 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
691 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
692 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
693 return Either.right(responseFormat);
696 // Setting name of grouping to fit the similar grouping name ignoring
698 // For example if Network-->kUKU exists for service sub-category
699 // Network, and user is trying to create grouping Router-->Kuku for
700 // service sub-category Router,
701 // his grouping name will be Router-->kUKU.
702 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
703 if (groupingUniqueForType.isRight()) {
704 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
705 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
706 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
707 return Either.right(responseFormat);
709 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
710 if (groupingDefinition != null) {
711 groupingName = groupingDefinition.getName();
714 grouping.setName(groupingName);
715 ///////////////////////////////////////////// Validations end
717 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
718 if (createGrouping.isRight()) {
719 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
720 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
721 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
722 return Either.right(responseFormat);
725 GroupingDefinition groupingCreated = createGrouping.left().value();
726 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
727 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
728 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
729 return Either.left(groupingCreated);
734 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
735 ResponseFormat responseFormat;
736 User user = new User();
737 if (userId == null) {
738 user.setUserId("UNKNOWN");
739 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
740 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
741 return Either.right(responseFormat);
744 user = validateUserExists(userId, "get All Categories", false);
745 } catch (ByActionStatusComponentException e){
746 responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
747 handleComponentException(componentType, userId, responseFormat);
749 } catch (ByResponseFormatComponentException e){
750 responseFormat = e.getResponseFormat();
751 handleComponentException(componentType, userId, responseFormat);
754 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
755 if (componentTypeEnum == null) {
756 log.debug("Cannot create category for component type {}", componentType);
757 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
758 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
759 return Either.right(responseFormat);
762 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
763 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
764 if (getAllCategoriesByType.isRight()) {
765 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
766 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
767 return Either.right(responseFormat);
769 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
770 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
771 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
772 return Either.left(categories);
777 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
778 ResponseFormat responseFormat;
779 UiCategories categories = new UiCategories();
781 User user = validateUserExists(userId, "get all categories", false);
783 // GET resource categories
784 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
785 if (getResourceCategoriesByType.isRight()) {
786 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
787 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
788 return Either.right(responseFormat);
790 categories.setResourceCategories(getResourceCategoriesByType.left().value());
792 // GET service categories
793 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
794 if (getServiceCategoriesByType.isRight()) {
795 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
796 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
797 return Either.right(responseFormat);
799 categories.setServiceCategories(getServiceCategoriesByType.left().value());
801 // GET product categories
802 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
803 if (getProductCategoriesByType.isRight()) {
804 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
805 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
806 return Either.right(responseFormat);
809 categories.setProductCategories(getProductCategoriesByType.left().value());
810 return Either.left(categories);
814 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
816 validateUserExists(userId, "delete Category", false);
818 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
819 if (componentTypeEnum == null) {
820 log.debug("Cannot create category for component type {}", componentTypeParamName);
821 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
824 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
826 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
827 if (deleteCategoryByType.isRight()) {
828 // auditing, logging here...
829 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
831 CategoryDefinition category = deleteCategoryByType.left().value();
832 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
833 return Either.left(category);
836 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String parentSubCategoryId, String componentTypeParamName, String userId) {
838 validateUserExists(userId, "delete Sub Category", false);
840 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
841 if (componentTypeEnum == null) {
842 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
843 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
846 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
848 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
849 if (deleteSubCategoryByType.isRight()) {
850 // auditing, logging here...
851 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
853 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
854 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
855 return Either.left(subCategory);
858 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String groupingId, String componentTypeParamName, String userId) {
860 validateUserExists(userId, "delete Grouping", false);
862 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
863 if (componentTypeEnum == null) {
864 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
865 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
868 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
870 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
871 if (deleteGroupingByType.isRight()) {
872 // auditing, logging here...
873 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
875 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
876 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
877 return Either.left(deletedGrouping);
880 private Either<User, ResponseFormat> validateUser(String userId) {
882 // validate user exists
883 if (userId == null) {
884 log.debug("UserId is null");
885 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
888 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
889 if (userResult.isRight()) {
890 ResponseFormat responseFormat;
891 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
892 log.debug("Not authorized user, userId = {}", userId);
893 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
895 log.debug("Failed to authorize user, userId = {}", userId);
896 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
899 return Either.right(responseFormat);
901 return Either.left(userResult.left().value());
902 // ========================================-
905 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
906 String role = user.getRole();
907 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
908 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
910 if (!(validAdminAction || validProductAction)) {
911 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
912 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
913 return Either.right(responseFormat);
915 return Either.left(true);
918 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
919 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
920 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
921 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
927 if (!(validResourceAction || validServiceAction || validProductAction)) {
928 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
929 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
930 return Either.right(responseFormat);
932 return Either.left(true);
935 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
936 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
937 if (categoryByTypeAndId.isRight()) {
938 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
939 ActionStatus actionStatus = categoryByTypeAndId.right().value();
940 ResponseFormat responseFormat;
941 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
942 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
944 responseFormat = componentsUtils.getResponseFormat(actionStatus);
946 return Either.right(responseFormat);
948 return Either.left(categoryByTypeAndId.left().value());
951 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
952 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
953 if (subCategoryByTypeAndId.isRight()) {
954 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
955 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
956 ResponseFormat responseFormat;
957 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
958 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
960 responseFormat = componentsUtils.getResponseFormat(actionStatus);
962 return Either.right(responseFormat);
964 return Either.left(subCategoryByTypeAndId.left().value());
967 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
968 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
971 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
972 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
975 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
976 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
980 * New categories flow - end
983 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
984 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
985 if (resp.isRight()) {
986 return Either.right(resp.right().value());
988 return elementOperation.getAllTags();
991 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
992 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
993 if (resp.isRight()) {
994 return Either.right(resp.right().value());
996 return elementOperation.getAllPropertyScopes();
999 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
1000 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
1001 if (resp.isRight()) {
1002 return Either.right(resp.right().value());
1004 return elementOperation.getAllArtifactTypes();
1007 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
1008 return elementOperation.getAllDeploymentArtifactTypes();
1011 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
1012 return elementOperation.getDefaultHeatTimeout();
1015 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId, List<OriginTypeEnum> excludeTypes) {
1017 validateUserExists(userId, "get Catalog Components", true);
1018 return toscaOperationFacade.getCatalogOrArchiveComponents(true, excludeTypes)
1019 .bimap(this::groupByComponentType,
1020 err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
1022 janusGraphDao.commit();
1026 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
1027 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
1029 // fixed response for UI!!! UI need to receive always map!
1031 map = new HashMap<>();
1033 if (map.get(RESOURCES) == null) {
1034 map.put(RESOURCES, new ArrayList());
1036 if (map.get(SERVICES) == null) {
1037 map.put(SERVICES, new ArrayList());
1042 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
1043 switch (componentTypeEnum) {
1049 throw new IllegalStateException("resources or services only");
1053 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1054 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1056 if (query != null) {
1057 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1058 if (invalidFilter.isPresent()) {
1059 log.debug("getFilteredAssetList: invalid filter key");
1060 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1064 if (filters == null || filters.isEmpty()) {
1065 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1066 if (componentsList.isRight()) {
1067 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1069 return Either.left(componentsList.left().value());
1072 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1074 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1075 if (result.isRight()) {
1076 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1077 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1079 if (result.left().value().isEmpty()) {// no assets found for requested
1081 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1083 return Either.left(result.left().value());
1086 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1087 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1088 if (assetType == ComponentTypeEnum.RESOURCE) {
1090 assetResult = getFilteredResouces(filters, inTransaction);
1092 } else if (assetType == ComponentTypeEnum.SERVICE) {
1094 assetResult = getFilteredServices(filters, inTransaction);
1099 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1101 Either<List<T>, StorageOperationStatus> components = null;
1103 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1104 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1105 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1106 if (distributionStatus != null && distEnum == null) {
1107 filters.remove(FilterKeyEnum.CATEGORY);
1108 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1111 if (categoryName != null) { // primary filter
1112 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1113 if (components.isLeft() && distEnum != null) {// secondary filter
1114 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1115 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1117 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1121 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1122 distStatusSet.add(distEnum);
1123 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1124 if (servicesWithDistStatus.isRight()) { // not found == empty list
1125 return Either.left(new ArrayList<>());
1128 return Either.left((List<T>) servicesWithDistStatus.left().value());
1131 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1133 if (assetType == null || uuid == null) {
1134 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1135 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1138 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1140 if (assetTypeEnum == null) {
1141 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1142 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1145 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1147 switch (assetTypeEnum) {
1149 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1152 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1155 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1156 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1159 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1160 if (componentsListByUuid.isRight()) {
1161 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1162 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1163 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1166 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1167 return Either.left(componentsListByUuid.left().value());
1170 public List<String> getAllComponentTypesParamNames() {
1171 List<String> paramNames = new ArrayList<>();
1172 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1173 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1174 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1178 public List<String> getAllSupportedRoles() {
1179 Role[] values = Role.values();
1180 List<String> roleNames = new ArrayList<>();
1181 for (Role role : values) {
1182 roleNames.add(role.name());
1187 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1188 return elementOperation.getResourceTypesMap();
1191 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1192 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1193 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1194 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1195 return params.stream().filter(noMatch).findAny();
1198 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1199 List<String> params = new ArrayList<>();
1200 if (1 == filters.size()) {
1201 params.add(assetType.getValue().toLowerCase());
1202 params.add(filters.keySet().iterator().next().getName());
1203 params.add(filters.values().iterator().next());
1205 params.add(assetType.getValue());
1206 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1207 params.add(filters.get(FilterKeyEnum.CATEGORY));
1212 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1214 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1215 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1216 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1217 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1218 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1220 if (categoryName != null) {
1221 subcategories = getAllSubCategories(categoryName);
1222 if (subcategories.isRight()) {
1223 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1224 return Either.right(subcategories.right().value());
1227 if (subCategoryName != null) { // primary filter
1228 if (categoryName != null) {
1229 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1230 if (!subCategoryData.isPresent()) {
1231 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1233 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction,
1234 ResourceMetadataData.class, resourceType);
1237 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1239 if (subcategories != null) {
1240 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1242 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1245 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1246 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1247 if (categoryResult.isRight()) {
1248 return Either.right(categoryResult.right().value());
1250 CategoryData categoryData = categoryResult.left().value();
1252 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
1253 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1254 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1255 if (childrenNodes.isRight()) {
1256 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(childrenNodes.right().value()));
1258 return Either.left(childrenNodes.left().value());
1261 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1262 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1263 return childNodes.stream().filter(matchName).findAny();
1266 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1267 Class<S> clazz, ResourceTypeEnum resourceType) {
1269 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1271 if (!inTransaction) {
1272 janusGraphDao.commit();
1277 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1278 Class<S> clazz, ResourceTypeEnum resourceType) {
1279 List<T> components = new ArrayList<>();
1281 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1282 Map<String, Object> props = new HashMap<>();
1283 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1284 Either<List<GraphNode>, JanusGraphOperationStatus> getCategory = janusGraphGenericDao.getByCriteria(categoryType, props, categoryClazz);
1285 if (getCategory.isRight()) {
1286 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1288 for (GraphNode category : getCategory.left().value()) {
1289 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1290 if (result.isRight()) {
1293 components.addAll(result.left().value());
1296 return Either.left(components);
1298 if (!inTransaction) {
1299 janusGraphDao.commit();
1305 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1306 List<T> components = new ArrayList<>();
1307 Either<List<ImmutablePair<S, GraphEdge>>, JanusGraphOperationStatus> parentNodes = janusGraphGenericDao
1308 .getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1309 if (parentNodes.isLeft()) {
1310 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1311 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1312 Boolean isHighest = componentData.isHighestVersion();
1313 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1314 boolean isDeleted = isTrue(componentData.isDeleted());
1315 boolean isArchived = isTrue(componentData.isArchived());
1317 if (isHighest && isMatchingResourceType && !isDeleted && !isArchived) {
1318 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1319 if (result.isRight()) {
1320 return Either.right(result.right().value());
1322 components.add(result.left().value());
1326 return Either.left(components);
1329 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1332 if (componentType == NodeTypeEnum.Resource) {
1333 if (resourceType == null) {
1336 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1344 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1345 List<T> components = new ArrayList<>();
1347 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1348 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource,
1349 inTransaction, ResourceMetadataData.class, resourceType);
1350 if (fetched.isRight()) {
1353 components.addAll(fetched.left().value());
1355 return Either.left(components);
1358 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1359 List<Component> components = null;
1360 StorageOperationStatus status;
1361 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1362 Either<List<Component>, StorageOperationStatus> result;
1364 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1365 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1366 if (getResources.isRight()) {
1367 status = getResources.right().value();
1368 if (status != StorageOperationStatus.NOT_FOUND) {
1369 statusWrapper.setInnerElement(getResources.right().value());
1371 components = new ArrayList<>();
1374 components = getResources.left().value();
1376 if (!statusWrapper.isEmpty()) {
1377 result = Either.right(statusWrapper.getInnerElement());
1379 result = Either.left(components);
1383 if (!inTransaction) {
1384 janusGraphDao.commit();