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.operations.api.IElementOperation;
50 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
51 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
52 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
53 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
54 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
55 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
56 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
57 import org.openecomp.sdc.be.resources.data.category.CategoryData;
58 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
59 import org.openecomp.sdc.be.ui.model.UiCategories;
60 import org.openecomp.sdc.be.user.Role;
61 import org.openecomp.sdc.be.user.UserBusinessLogic;
62 import org.openecomp.sdc.common.datastructure.Wrapper;
63 import org.openecomp.sdc.common.log.wrappers.Logger;
64 import org.openecomp.sdc.common.util.ValidationUtils;
65 import org.openecomp.sdc.exception.ResponseFormat;
67 import java.nio.charset.StandardCharsets;
69 import java.util.function.Predicate;
70 import java.util.stream.Collectors;
72 import static org.apache.commons.lang.BooleanUtils.isTrue;
74 @org.springframework.stereotype.Component("elementsBusinessLogic")
75 public class ElementBusinessLogic extends BaseBusinessLogic {
77 private static final Logger log = Logger.getLogger(ElementBusinessLogic.class);
78 private static final String SERVICES = "services";
79 private static final String RESOURCES = "resources";
80 private static final String VALIDATION_OF_USER_FAILED_USER_ID = "Validation of user failed, userId {}";
81 private static final String COMPONENT_TYPE_IS_INVALID = "Component type {} is invalid";
82 private static final String VALIDATION_OF_USER_ROLE_FAILED_USER_ID = "Validation of user role failed, userId {}";
84 @javax.annotation.Resource
85 private IElementOperation elementOperation;
87 @javax.annotation.Resource
88 private UserBusinessLogic userAdminManager;
95 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
96 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
97 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
99 String role = user.getRole();
100 String userId = user.getUserId();
101 Role currentRole = Role.valueOf(role);
103 switch (currentRole) {
105 response = handleDesigner(userId);
109 response = handleTester();
113 response = handleGovernor();
117 response = handleOps();
120 case PRODUCT_STRATEGIST:
121 response = handleProductStrategist();
124 case PRODUCT_MANAGER:
125 response = handleProductManager(userId);
129 response = handleAdmin();
133 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
136 // 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)
137 return convertedToListResponse(response);
141 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
143 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
144 if (setResponse.isLeft()) {
145 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
146 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
148 return Either.left(arrayResponse);
150 return Either.right(setResponse.right().value());
153 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
154 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
155 // userId should stay null
156 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
157 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
158 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
159 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
163 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
164 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
165 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
166 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
167 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
168 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
169 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
170 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
171 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
173 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
174 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
178 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleGovernor() {
179 return handleFollowedCertifiedServices(null);
182 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist() {
183 // Should be empty list according to Ella, 13/03/16
184 Map<String, Set<? extends Component>> result = new HashMap<>();
185 result.put("products", new HashSet<>());
186 return Either.left(result);
189 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
190 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
191 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
192 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
193 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
194 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
195 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
196 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
197 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
199 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
200 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
204 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleOps() {
205 Set<DistributionStatusEnum> distStatus = new HashSet<>();
206 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
207 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
209 return handleFollowedCertifiedServices(distStatus);
212 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
214 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
215 if (services.isLeft()) {
216 Map<String, Set<? extends Component>> result = new HashMap<>();
217 Set<Service> set = new HashSet<>();
218 set.addAll(services.left().value());
219 result.put(SERVICES, set);
220 return Either.left(result);
222 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
226 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleTester() {
227 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
228 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
229 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
231 return getFollowedResourcesAndServices(null, lifecycleStates, null);
234 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
237 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
239 if (resources.isLeft()) {
240 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
241 if (services.isLeft()) {
242 Map<String, Set<? extends Component>> result = new HashMap<>();
243 result.put(SERVICES, services.left().value());
244 result.put(RESOURCES, resources.left().value());
245 return Either.left(result);
247 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
250 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
253 janusGraphDao.commit();
257 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
258 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
259 if (products.isLeft()) {
260 Map<String, Set<? extends Component>> result = new HashMap<>();
261 result.put("products", products.left().value());
262 return Either.left(result);
264 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
269 * New categories flow - start
271 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
272 return elementOperation.getAllResourceCategories();
275 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
276 return elementOperation.getAllServiceCategories();
279 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
281 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
282 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
283 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
284 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
287 Either<User, ResponseFormat> validateUser = validateUser(userId);
288 if (validateUser.isRight()) {
289 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
290 ResponseFormat responseFormat = validateUser.right().value();
292 user.setUserId(userId);
293 String currCategoryName = (category == null ? null : category.getName());
294 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
295 return Either.right(responseFormat);
298 user = validateUser.left().value();
300 if (category == null) {
301 log.debug("Category json is invalid");
302 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
303 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
304 return Either.right(responseFormat);
307 String categoryName = category.getName();
308 // For auditing of failures we need the original non-normalized name
309 String origCategoryName = categoryName;
310 if (componentTypeEnum == null) {
311 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
312 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
313 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
314 return Either.right(responseFormat);
317 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
318 if (validateUserRole.isRight()) {
319 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
320 ResponseFormat responseFormat = validateUserRole.right().value();
321 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
322 return Either.right(responseFormat);
325 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
326 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
327 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
328 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
329 return Either.right(responseFormat);
332 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
334 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
335 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
336 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
337 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
338 return Either.right(responseFormat);
341 category.setName(categoryName);
343 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
344 category.setNormalizedName(normalizedName);
346 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
348 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
349 if (categoryUniqueEither.isRight()) {
350 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
351 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
352 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
353 return Either.right(responseFormat);
356 Boolean isCategoryUnique = categoryUniqueEither.left().value();
357 if (!isCategoryUnique) {
358 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
359 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
360 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
361 return Either.right(responseFormat);
364 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
365 if (createCategoryByType.isRight()) {
366 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
367 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
368 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
369 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
371 category = createCategoryByType.left().value();
372 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
373 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
374 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
375 return Either.left(category);
378 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
380 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
381 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
382 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
383 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
385 String parentCategoryName = parentCategoryId;
387 if (subCategory == null) {
388 log.debug("Sub-category json is invalid");
389 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
390 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
391 return Either.right(responseFormat);
394 String subCategoryName = subCategory.getName();
395 // For auditing of failures we need the original non-normalized name
396 String origSubCategoryName = subCategoryName;
399 user = validateUserExists(userId, "createSubCategory", false);
400 } catch(ByActionStatusComponentException e){
401 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
402 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName,
405 } catch(ByResponseFormatComponentException e){
406 ResponseFormat responseFormat = e.getResponseFormat();
407 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName,
411 if (componentTypeEnum == null) {
412 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
413 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
414 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
415 return Either.right(responseFormat);
418 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
419 if (validateComponentType.isRight()) {
420 log.debug("Validation of component type for sub-category failed");
421 ResponseFormat responseFormat = validateComponentType.right().value();
422 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
423 return Either.right(responseFormat);
426 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
427 if (validateUserRole.isRight()) {
428 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
429 ResponseFormat responseFormat = validateUserRole.right().value();
430 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
431 return Either.right(responseFormat);
434 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
435 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
437 CategoryDefinition categoryDefinition;
438 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
439 if (validateCategoryExists.isRight()) {
440 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
441 ResponseFormat responseFormat = validateCategoryExists.right().value();
442 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
443 return Either.right(responseFormat);
446 categoryDefinition = validateCategoryExists.left().value();
447 parentCategoryName = categoryDefinition.getName();
449 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
450 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
451 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
452 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
453 return Either.right(responseFormat);
456 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
458 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
459 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
460 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
461 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
462 return Either.right(responseFormat);
465 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
466 subCategory.setNormalizedName(normalizedName);
468 // Uniqueness under this category
469 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
470 if (subCategoryUniqueForCategory.isRight()) {
471 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
472 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
473 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
474 return Either.right(responseFormat);
477 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
479 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
480 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
481 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
482 return Either.right(responseFormat);
485 // Setting name of subcategory to fit the similar subcategory name
487 // For example if Network-->kUKU exists for service category Network,
488 // and user is trying to create Router-->Kuku for service category
490 // his subcategory name will be Router-->kUKU.
491 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
492 if (subCategoryUniqueForType.isRight()) {
493 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
494 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
495 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
496 return Either.right(responseFormat);
498 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
499 if (subCategoryDefinition != null) {
500 subCategoryName = subCategoryDefinition.getName();
503 subCategory.setName(subCategoryName);
504 ///////////////////////////////////////////// Validations end
506 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
507 if (createSubCategory.isRight()) {
508 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
509 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
510 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
511 return Either.right(responseFormat);
514 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
515 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
516 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
517 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
518 return Either.left(subCategoryCreated);
521 private void handleComponentException(String userId, AuditingActionEnum auditingAction, String componentType,
522 String parentCategoryName, String origSubCategoryName, ResponseFormat responseFormat) {
524 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
526 user.setUserId(userId);
527 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction,
531 private void handleComponentException(GroupingDefinition grouping, String userId, AuditingActionEnum auditingAction,
532 String componentType, String parentCategoryName, String parentSubCategoryName, ResponseFormat responseFormat) {
534 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
536 user.setUserId(userId);
537 String groupingNameForAudit = grouping == null ? null : grouping.getName();
538 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit,
539 auditingAction, componentType);
542 private void handleComponentException(String componentType, String userId, ResponseFormat responseFormat) {
545 user.setUserId(userId);
546 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
547 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
550 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
552 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
553 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
554 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
555 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
557 String parentCategoryName = grandParentCategoryId;
558 String parentSubCategoryName = parentSubCategoryId;
562 user = validateUserExists(userId, "create Grouping", false);
563 } catch(ByResponseFormatComponentException e){
564 ResponseFormat responseFormat = e.getResponseFormat();
565 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName,
566 parentSubCategoryName,
569 } catch(ByActionStatusComponentException e){
570 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
571 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName,
572 parentSubCategoryName, responseFormat);
576 if (grouping == null) {
577 log.debug("Grouping json is invalid");
578 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
579 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
580 return Either.right(responseFormat);
583 String groupingName = grouping.getName();
584 // For auditing of failures we need the original non-normalized name
585 String origGroupingName = groupingName;
587 if (componentTypeEnum == null) {
588 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
589 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
590 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
591 return Either.right(responseFormat);
594 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
595 if (validateComponentType.isRight()) {
596 log.debug("Validation of component type for grouping failed");
597 ResponseFormat responseFormat = validateComponentType.right().value();
598 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
599 return Either.right(responseFormat);
602 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
603 if (validateUserRole.isRight()) {
604 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
605 ResponseFormat responseFormat = validateUserRole.right().value();
606 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
607 return Either.right(responseFormat);
610 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
611 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
612 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
615 CategoryDefinition categoryDefinition;
616 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
617 if (validateCategoryExists.isRight()) {
618 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
619 ResponseFormat responseFormat = validateCategoryExists.right().value();
620 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
621 return Either.right(responseFormat);
624 categoryDefinition = validateCategoryExists.left().value();
625 parentCategoryName = categoryDefinition.getName();
627 // Validate subcategory
628 SubCategoryDefinition subCategoryDefinition;
629 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
630 if (validateSubCategoryExists.isRight()) {
631 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
632 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
633 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
634 return Either.right(responseFormat);
637 subCategoryDefinition = validateSubCategoryExists.left().value();
638 parentSubCategoryName = subCategoryDefinition.getName();
640 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
641 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
642 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
643 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
644 return Either.right(responseFormat);
647 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
649 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
650 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
651 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
652 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
653 return Either.right(responseFormat);
656 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
657 grouping.setNormalizedName(normalizedName);
659 // Uniqueness under this category
660 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
661 if (groupingUniqueForSubCategory.isRight()) {
662 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
663 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
664 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
665 return Either.right(responseFormat);
668 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
669 if (!isGroupingUnique) {
670 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
671 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
672 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
673 return Either.right(responseFormat);
676 // Setting name of grouping to fit the similar grouping name ignoring
678 // For example if Network-->kUKU exists for service sub-category
679 // Network, and user is trying to create grouping Router-->Kuku for
680 // service sub-category Router,
681 // his grouping name will be Router-->kUKU.
682 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
683 if (groupingUniqueForType.isRight()) {
684 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
685 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
686 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
687 return Either.right(responseFormat);
689 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
690 if (groupingDefinition != null) {
691 groupingName = groupingDefinition.getName();
694 grouping.setName(groupingName);
695 ///////////////////////////////////////////// Validations end
697 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
698 if (createGrouping.isRight()) {
699 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
700 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
701 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
702 return Either.right(responseFormat);
705 GroupingDefinition groupingCreated = createGrouping.left().value();
706 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
707 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
708 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
709 return Either.left(groupingCreated);
714 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
715 ResponseFormat responseFormat;
716 User user = new User();
717 if (userId == null) {
718 user.setUserId("UNKNOWN");
719 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
720 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
721 return Either.right(responseFormat);
724 user = validateUserExists(userId, "get All Categories", false);
725 } catch (ByActionStatusComponentException e){
726 responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
727 handleComponentException(componentType, userId, responseFormat);
729 } catch (ByResponseFormatComponentException e){
730 responseFormat = e.getResponseFormat();
731 handleComponentException(componentType, userId, responseFormat);
734 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
735 if (componentTypeEnum == null) {
736 log.debug("Cannot create category for component type {}", componentType);
737 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
738 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
739 return Either.right(responseFormat);
742 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
743 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
744 if (getAllCategoriesByType.isRight()) {
745 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
746 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
747 return Either.right(responseFormat);
749 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
750 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
751 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
752 return Either.left(categories);
757 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
758 ResponseFormat responseFormat;
759 UiCategories categories = new UiCategories();
761 User user = validateUserExists(userId, "get all categories", false);
763 // GET resource categories
764 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
765 if (getResourceCategoriesByType.isRight()) {
766 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
767 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
768 return Either.right(responseFormat);
770 categories.setResourceCategories(getResourceCategoriesByType.left().value());
772 // GET service categories
773 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
774 if (getServiceCategoriesByType.isRight()) {
775 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
776 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
777 return Either.right(responseFormat);
779 categories.setServiceCategories(getServiceCategoriesByType.left().value());
781 // GET product categories
782 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
783 if (getProductCategoriesByType.isRight()) {
784 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
785 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
786 return Either.right(responseFormat);
789 categories.setProductCategories(getProductCategoriesByType.left().value());
790 return Either.left(categories);
794 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
796 validateUserExists(userId, "delete Category", false);
798 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
799 if (componentTypeEnum == null) {
800 log.debug("Cannot create category for component type {}", componentTypeParamName);
801 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
804 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
806 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
807 if (deleteCategoryByType.isRight()) {
808 // auditing, logging here...
809 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
811 CategoryDefinition category = deleteCategoryByType.left().value();
812 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
813 return Either.left(category);
816 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String parentSubCategoryId, String componentTypeParamName, String userId) {
818 validateUserExists(userId, "delete Sub Category", false);
820 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
821 if (componentTypeEnum == null) {
822 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
823 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
826 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
828 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
829 if (deleteSubCategoryByType.isRight()) {
830 // auditing, logging here...
831 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
833 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
834 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
835 return Either.left(subCategory);
838 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String groupingId, String componentTypeParamName, String userId) {
840 validateUserExists(userId, "delete Grouping", false);
842 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
843 if (componentTypeEnum == null) {
844 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
845 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
848 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
850 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
851 if (deleteGroupingByType.isRight()) {
852 // auditing, logging here...
853 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
855 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
856 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
857 return Either.left(deletedGrouping);
860 private Either<User, ResponseFormat> validateUser(String userId) {
862 // validate user exists
863 if (userId == null) {
864 log.debug("UserId is null");
865 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
868 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
869 if (userResult.isRight()) {
870 ResponseFormat responseFormat;
871 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
872 log.debug("Not authorized user, userId = {}", userId);
873 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
875 log.debug("Failed to authorize user, userId = {}", userId);
876 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
879 return Either.right(responseFormat);
881 return Either.left(userResult.left().value());
882 // ========================================-
885 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
886 String role = user.getRole();
887 boolean validAdminAction = role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
888 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
890 if (!(validAdminAction || validProductAction)) {
891 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
892 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
893 return Either.right(responseFormat);
895 return Either.left(true);
898 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
899 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY);
900 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
901 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
907 if (!(validResourceAction || validServiceAction || validProductAction)) {
908 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
909 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
910 return Either.right(responseFormat);
912 return Either.left(true);
915 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
916 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
917 if (categoryByTypeAndId.isRight()) {
918 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
919 ActionStatus actionStatus = categoryByTypeAndId.right().value();
920 ResponseFormat responseFormat;
921 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
922 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
924 responseFormat = componentsUtils.getResponseFormat(actionStatus);
926 return Either.right(responseFormat);
928 return Either.left(categoryByTypeAndId.left().value());
931 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
932 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
933 if (subCategoryByTypeAndId.isRight()) {
934 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
935 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
936 ResponseFormat responseFormat;
937 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
938 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
940 responseFormat = componentsUtils.getResponseFormat(actionStatus);
942 return Either.right(responseFormat);
944 return Either.left(subCategoryByTypeAndId.left().value());
947 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
948 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
951 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
952 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
955 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
956 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
960 * New categories flow - end
963 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
964 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
965 if (resp.isRight()) {
966 return Either.right(resp.right().value());
968 return elementOperation.getAllTags();
971 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
972 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
973 if (resp.isRight()) {
974 return Either.right(resp.right().value());
976 return elementOperation.getAllPropertyScopes();
979 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
980 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
981 if (resp.isRight()) {
982 return Either.right(resp.right().value());
984 return elementOperation.getAllArtifactTypes();
987 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
988 return elementOperation.getAllDeploymentArtifactTypes();
991 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
992 return elementOperation.getDefaultHeatTimeout();
995 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(String userId, List<OriginTypeEnum> excludeTypes) {
997 validateUserExists(userId, "get Catalog Components", true);
998 return toscaOperationFacade.getCatalogOrArchiveComponents(true, excludeTypes)
999 .bimap(this::groupByComponentType,
1000 err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
1002 janusGraphDao.commit();
1006 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
1007 Map<String, List<CatalogComponent>> map = components.stream().collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
1009 // fixed response for UI!!! UI need to receive always map!
1011 map = new HashMap<>();
1013 if (map.get(RESOURCES) == null) {
1014 map.put(RESOURCES, new ArrayList());
1016 if (map.get(SERVICES) == null) {
1017 map.put(SERVICES, new ArrayList());
1022 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
1023 switch (componentTypeEnum) {
1029 throw new IllegalStateException("resources or services only");
1033 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1034 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1036 if (query != null) {
1037 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1038 if (invalidFilter.isPresent()) {
1039 log.debug("getFilteredAssetList: invalid filter key");
1040 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1044 if (filters == null || filters.isEmpty()) {
1045 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
1046 if (componentsList.isRight()) {
1047 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1049 return Either.left(componentsList.left().value());
1052 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1054 // category hierarchy mismatch or category/subCategory/distributionStatus not found
1055 if (result.isRight()) {
1056 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1057 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1059 if (result.left().value().isEmpty()) {// no assets found for requested
1061 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1063 return Either.left(result.left().value());
1066 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1067 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
1068 if (assetType == ComponentTypeEnum.RESOURCE) {
1070 assetResult = getFilteredResouces(filters, inTransaction);
1072 } else if (assetType == ComponentTypeEnum.SERVICE) {
1074 assetResult = getFilteredServices(filters, inTransaction);
1079 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1081 Either<List<T>, StorageOperationStatus> components = null;
1083 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1084 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1085 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1086 if (distributionStatus != null && distEnum == null) {
1087 filters.remove(FilterKeyEnum.CATEGORY);
1088 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1091 if (categoryName != null) { // primary filter
1092 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1093 if (components.isLeft() && distEnum != null) {// secondary filter
1094 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1095 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1097 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1101 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1102 distStatusSet.add(distEnum);
1103 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1104 if (servicesWithDistStatus.isRight()) { // not found == empty list
1105 return Either.left(new ArrayList<>());
1108 return Either.left((List<T>) servicesWithDistStatus.left().value());
1111 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1113 if (assetType == null || uuid == null) {
1114 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1115 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1118 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1120 if (assetTypeEnum == null) {
1121 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1122 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1125 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1127 switch (assetTypeEnum) {
1129 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1132 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1135 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1136 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1139 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1140 if (componentsListByUuid.isRight()) {
1141 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1142 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1143 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1146 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1147 return Either.left(componentsListByUuid.left().value());
1150 public List<String> getAllComponentTypesParamNames() {
1151 List<String> paramNames = new ArrayList<>();
1152 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1153 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1154 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1158 public List<String> getAllSupportedRoles() {
1159 Role[] values = Role.values();
1160 List<String> roleNames = new ArrayList<>();
1161 for (Role role : values) {
1162 roleNames.add(role.name());
1167 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1168 return elementOperation.getResourceTypesMap();
1171 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1172 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1173 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1174 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1175 return params.stream().filter(noMatch).findAny();
1178 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1179 List<String> params = new ArrayList<>();
1180 if (1 == filters.size()) {
1181 params.add(assetType.getValue().toLowerCase());
1182 params.add(filters.keySet().iterator().next().getName());
1183 params.add(filters.values().iterator().next());
1185 params.add(assetType.getValue());
1186 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1187 params.add(filters.get(FilterKeyEnum.CATEGORY));
1192 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1194 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1195 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1196 ResourceTypeEnum resourceType = ResourceTypeEnum.getType(filters.get(FilterKeyEnum.RESOURCE_TYPE));
1197 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1198 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1200 if (categoryName != null) {
1201 subcategories = getAllSubCategories(categoryName);
1202 if (subcategories.isRight()) {
1203 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1204 return Either.right(subcategories.right().value());
1207 if (subCategoryName != null) { // primary filter
1208 if (categoryName != null) {
1209 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1210 if (!subCategoryData.isPresent()) {
1211 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1213 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction,
1214 ResourceMetadataData.class, resourceType);
1217 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1219 if (subcategories != null) {
1220 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1222 return fetchComponentMetaDataByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1225 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1226 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1227 if (categoryResult.isRight()) {
1228 return Either.right(categoryResult.right().value());
1230 CategoryData categoryData = categoryResult.left().value();
1232 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
1233 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1234 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1235 if (childrenNodes.isRight()) {
1236 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(childrenNodes.right().value()));
1238 return Either.left(childrenNodes.left().value());
1241 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1242 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1243 return childNodes.stream().filter(matchName).findAny();
1246 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1247 Class<S> clazz, ResourceTypeEnum resourceType) {
1249 return collectComponents(neededType, categoryUid, categoryType, clazz, resourceType);
1251 if (!inTransaction) {
1252 janusGraphDao.commit();
1257 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, NodeTypeEnum neededType, boolean inTransaction,
1258 Class<S> clazz, ResourceTypeEnum resourceType) {
1259 List<T> components = new ArrayList<>();
1261 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1262 Map<String, Object> props = new HashMap<>();
1263 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1264 Either<List<GraphNode>, JanusGraphOperationStatus> getCategory = janusGraphGenericDao
1265 .getByCriteria(categoryType, props, categoryClazz);
1266 if (getCategory.isRight()) {
1267 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1269 for (GraphNode category : getCategory.left().value()) {
1270 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1271 if (result.isRight()) {
1274 components.addAll(result.left().value());
1277 return Either.left(components);
1279 if (!inTransaction) {
1280 janusGraphDao.commit();
1286 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1287 List<T> components = new ArrayList<>();
1288 Either<List<ImmutablePair<S, GraphEdge>>, JanusGraphOperationStatus> parentNodes = janusGraphGenericDao
1289 .getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1290 if (parentNodes.isLeft()) {
1291 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1292 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1293 Boolean isHighest = componentData.isHighestVersion();
1294 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1295 boolean isDeleted = isTrue(componentData.isDeleted());
1296 boolean isArchived = isTrue(componentData.isArchived());
1298 if (isHighest && isMatchingResourceType && !isDeleted && !isArchived) {
1299 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1300 if (result.isRight()) {
1301 return Either.right(result.right().value());
1303 components.add(result.left().value());
1307 return Either.left(components);
1310 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType, ComponentMetadataDataDefinition componentData) {
1313 if (componentType == NodeTypeEnum.Resource) {
1314 if (resourceType == null) {
1317 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1325 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1326 List<T> components = new ArrayList<>();
1328 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1329 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource,
1330 inTransaction, ResourceMetadataData.class, resourceType);
1331 if (fetched.isRight()) {
1334 components.addAll(fetched.left().value());
1336 return Either.left(components);
1339 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1340 List<Component> components = null;
1341 StorageOperationStatus status;
1342 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1343 Either<List<Component>, StorageOperationStatus> result;
1345 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1346 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1347 if (getResources.isRight()) {
1348 status = getResources.right().value();
1349 if (status != StorageOperationStatus.NOT_FOUND) {
1350 statusWrapper.setInnerElement(getResources.right().value());
1352 components = new ArrayList<>();
1355 components = getResources.left().value();
1357 if (!statusWrapper.isEmpty()) {
1358 result = Either.right(statusWrapper.getInnerElement());
1360 result = Either.left(components);
1364 if (!inTransaction) {
1365 janusGraphDao.commit();