2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.components.impl;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
29 import java.util.Optional;
31 import java.util.function.Predicate;
32 import java.util.stream.Collectors;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.apache.http.NameValuePair;
36 import org.apache.http.client.utils.URLEncodedUtils;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
39 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
40 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
41 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
42 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
43 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
44 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
45 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
46 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
47 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
48 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
49 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
50 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
51 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
52 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
53 import org.openecomp.sdc.be.impl.ComponentsUtils;
54 import org.openecomp.sdc.be.model.ArtifactType;
55 import org.openecomp.sdc.be.model.Component;
56 import org.openecomp.sdc.be.model.DistributionStatusEnum;
57 import org.openecomp.sdc.be.model.LifecycleStateEnum;
58 import org.openecomp.sdc.be.model.Product;
59 import org.openecomp.sdc.be.model.PropertyScope;
60 import org.openecomp.sdc.be.model.Resource;
61 import org.openecomp.sdc.be.model.ResourceMetadataDefinition;
62 import org.openecomp.sdc.be.model.Service;
63 import org.openecomp.sdc.be.model.Tag;
64 import org.openecomp.sdc.be.model.User;
65 import org.openecomp.sdc.be.model.category.CategoryDefinition;
66 import org.openecomp.sdc.be.model.category.GroupingDefinition;
67 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
68 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
69 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
70 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
71 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
72 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
73 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
74 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
75 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
76 import org.openecomp.sdc.be.resources.data.category.CategoryData;
77 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
78 import org.openecomp.sdc.be.ui.model.UiCategories;
79 import org.openecomp.sdc.be.user.Role;
80 import org.openecomp.sdc.be.user.UserBusinessLogic;
81 import org.openecomp.sdc.common.datastructure.Wrapper;
82 import org.openecomp.sdc.common.util.ValidationUtils;
83 import org.openecomp.sdc.exception.ResponseFormat;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
87 import com.thinkaurelius.titan.core.TitanGraph;
89 import fj.data.Either;
91 @org.springframework.stereotype.Component("elementsBusinessLogic")
92 public class ElementBusinessLogic extends BaseBusinessLogic {
94 private static Logger log = LoggerFactory.getLogger(ElementBusinessLogic.class.getName());
96 @javax.annotation.Resource
97 private IElementOperation elementOperation;
99 @javax.annotation.Resource
100 private ComponentsUtils componentsUtils;
102 @javax.annotation.Resource
103 private UserBusinessLogic userAdminManager;
110 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
111 Either<Map<String, List<? extends Component>>, ResponseFormat> response = null;
113 String role = user.getRole();
114 String userId = null;
115 Role currentRole = Role.valueOf(role);
117 switch (currentRole) {
119 userId = user.getUserId();
120 response = handleDesigner(userId);
124 userId = user.getUserId();
125 response = handleTester(userId);
129 userId = user.getUserId();
130 response = handleGovernor(userId);
134 userId = user.getUserId();
135 response = handleOps(userId);
138 case PRODUCT_STRATEGIST:
139 userId = user.getUserId();
140 response = handleProductStrategist(userId);
143 case PRODUCT_MANAGER:
144 userId = user.getUserId();
145 response = handleProductManager(userId);
149 response = handleAdmin();
153 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
160 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleAdmin() {
161 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
162 // userId should stay null
163 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
164 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
165 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
166 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
170 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
171 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
172 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
173 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
174 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
175 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
176 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
177 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
178 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
180 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
181 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
185 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleGovernor(String userId) {
186 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(null);
190 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductStrategist(String userId) {
191 // Should be empty list according to Ella, 13/03/16
192 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
193 result.put("products", new ArrayList<>());
194 return Either.left(result);
197 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
198 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
199 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
200 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
201 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
202 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
203 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
204 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
205 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
207 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
208 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
212 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleOps(String userId) {
213 Set<DistributionStatusEnum> distStatus = new HashSet<DistributionStatusEnum>();
214 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
215 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
217 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(distStatus);
221 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
223 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
224 if (services.isLeft()) {
225 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
226 List<Service> list = new ArrayList<>();
227 list.addAll(services.left().value());
228 result.put("services", list);
229 return Either.left(result);
231 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
235 private Either<Map<String, List<? extends Component>>, ResponseFormat> handleTester(String userId) {
236 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
237 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
238 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
239 Either<Map<String, List<? extends Component>>, ResponseFormat> result = getFollowedResourcesAndServices(null, lifecycleStates, null);
244 private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
247 Either<List<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
249 if (resources.isLeft()) {
250 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
251 if (services.isLeft()) {
252 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
253 result.put("services", services.left().value());
254 result.put("resources", resources.left().value());
255 return Either.left(result);
257 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
260 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
267 private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
268 Either<List<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
269 if (products.isLeft()) {
270 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
271 result.put("products", products.left().value());
272 return Either.left(result);
274 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
279 * New categories flow - start
281 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
282 return elementOperation.getAllResourceCategories();
285 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
286 return elementOperation.getAllServiceCategories();
289 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
291 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
292 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
293 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
294 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
296 User user = new User();
297 Either<User, ResponseFormat> validateUser = validateUser(userId);
298 if (validateUser.isRight()) {
299 log.debug("Validation of user failed, userId {}", userId);
300 ResponseFormat responseFormat = validateUser.right().value();
302 user.setUserId(userId);
303 String currCategoryName = (category == null ? null : category.getName());
304 handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
305 return Either.right(responseFormat);
308 user = validateUser.left().value();
310 if (category == null) {
311 log.debug("Category json is invalid");
312 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
313 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
314 return Either.right(responseFormat);
317 String categoryName = category.getName();
318 // For auditing of failures we need the original non-normalized name
319 String origCategoryName = categoryName;
320 if (componentTypeEnum == null) {
321 log.debug("Component type {} is invalid", componentTypeParamName);
322 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
323 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
324 return Either.right(responseFormat);
327 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
328 if (validateUserRole.isRight()) {
329 log.debug("Validation of user role failed, userId {}", userId);
330 ResponseFormat responseFormat = validateUserRole.right().value();
331 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
332 return Either.right(responseFormat);
335 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
336 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
337 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
338 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
339 return Either.right(responseFormat);
342 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
344 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
345 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
346 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
347 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
348 return Either.right(responseFormat);
351 category.setName(categoryName);
353 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
354 category.setNormalizedName(normalizedName);
356 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
358 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
359 if (categoryUniqueEither.isRight()) {
360 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
361 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
362 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
363 return Either.right(responseFormat);
366 Boolean isCategoryUnique = categoryUniqueEither.left().value();
367 if (!isCategoryUnique) {
368 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
369 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
370 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
371 return Either.right(responseFormat);
374 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
375 if (createCategoryByType.isRight()) {
376 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
377 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
378 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
379 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
381 category = createCategoryByType.left().value();
382 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
383 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
384 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
385 return Either.left(category);
388 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
390 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
391 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
392 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
393 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
395 String parentCategoryName = parentCategoryId;
397 if (subCategory == null) {
398 log.debug("Sub-category json is invalid");
399 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
400 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
401 return Either.right(responseFormat);
404 String subCategoryName = subCategory.getName();
405 // For auditing of failures we need the original non-normalized name
406 String origSubCategoryName = subCategoryName;
408 User user = new User();
409 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "createSubCategory", false);
410 if (validateUser.isRight()) {
411 log.debug("Validation of user failed, userId {}", userId);
412 ResponseFormat responseFormat = validateUser.right().value();
414 user.setUserId(userId);
415 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
416 return Either.right(responseFormat);
419 user = validateUser.left().value();
421 if (componentTypeEnum == null) {
422 log.debug("Component type {} is invalid", componentTypeParamName);
423 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
424 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
425 return Either.right(responseFormat);
428 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
429 if (validateComponentType.isRight()) {
430 log.debug("Validation of component type for sub-category failed");
431 ResponseFormat responseFormat = validateComponentType.right().value();
432 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
433 return Either.right(responseFormat);
436 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
437 if (validateUserRole.isRight()) {
438 log.debug("Validation of user role failed, userId {}", userId);
439 ResponseFormat responseFormat = validateUserRole.right().value();
440 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
441 return Either.right(responseFormat);
444 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
445 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
447 CategoryDefinition categoryDefinition;
448 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
449 if (validateCategoryExists.isRight()) {
450 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
451 ResponseFormat responseFormat = validateCategoryExists.right().value();
452 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
453 return Either.right(responseFormat);
456 categoryDefinition = validateCategoryExists.left().value();
457 parentCategoryName = categoryDefinition.getName();
459 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
460 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
461 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
462 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
463 return Either.right(responseFormat);
466 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
468 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
469 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
470 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
471 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
472 return Either.right(responseFormat);
475 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
476 subCategory.setNormalizedName(normalizedName);
478 // Uniqueness under this category
479 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
480 if (subCategoryUniqueForCategory.isRight()) {
481 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
482 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
483 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
484 return Either.right(responseFormat);
487 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
489 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
490 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
491 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
492 return Either.right(responseFormat);
495 // Setting name of subcategory to fit the similar subcategory name
497 // For example if Network-->kUKU exists for service category Network,
498 // and user is trying to create Router-->Kuku for service category
500 // his subcategory name will be Router-->kUKU.
501 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
502 if (subCategoryUniqueForType.isRight()) {
503 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
504 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
505 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
506 return Either.right(responseFormat);
508 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
509 if (subCategoryDefinition != null) {
510 subCategoryName = subCategoryDefinition.getName();
513 subCategory.setName(subCategoryName);
514 ///////////////////////////////////////////// Validations end
516 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
517 if (createSubCategory.isRight()) {
518 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
519 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
520 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
521 return Either.right(responseFormat);
524 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
525 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
526 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
527 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
528 return Either.left(subCategoryCreated);
531 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
533 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
534 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
535 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
536 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
538 String parentCategoryName = grandParentCategoryId;
539 String parentSubCategoryName = parentSubCategoryId;
542 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "create Grouping", false);
543 if (validateUser.isRight()) {
544 log.debug("Validation of user failed, userId {}", userId);
545 ResponseFormat responseFormat = validateUser.right().value();
547 user.setUserId(userId);
548 String groupingNameForAudit = (grouping == null ? null : grouping.getName());
549 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
550 return Either.right(responseFormat);
553 user = validateUser.left().value();
555 if (grouping == null) {
556 log.debug("Grouping json is invalid");
557 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
558 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
559 return Either.right(responseFormat);
562 String groupingName = grouping.getName();
563 // For auditing of failures we need the original non-normalized name
564 String origGroupingName = groupingName;
566 if (componentTypeEnum == null) {
567 log.debug("Component type {} is invalid", componentTypeParamName);
568 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
569 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
570 return Either.right(responseFormat);
573 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
574 if (validateComponentType.isRight()) {
575 log.debug("Validation of component type for grouping failed");
576 ResponseFormat responseFormat = validateComponentType.right().value();
577 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
578 return Either.right(responseFormat);
581 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
582 if (validateUserRole.isRight()) {
583 log.debug("Validation of user role failed, userId {}", userId);
584 ResponseFormat responseFormat = validateUserRole.right().value();
585 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
586 return Either.right(responseFormat);
589 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
590 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
591 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
594 CategoryDefinition categoryDefinition;
595 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
596 if (validateCategoryExists.isRight()) {
597 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
598 ResponseFormat responseFormat = validateCategoryExists.right().value();
599 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
600 return Either.right(responseFormat);
603 categoryDefinition = validateCategoryExists.left().value();
604 parentCategoryName = categoryDefinition.getName();
606 // Validate subcategory
607 SubCategoryDefinition subCategoryDefinition;
608 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
609 if (validateSubCategoryExists.isRight()) {
610 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
611 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
612 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
613 return Either.right(responseFormat);
616 subCategoryDefinition = validateSubCategoryExists.left().value();
617 parentSubCategoryName = subCategoryDefinition.getName();
619 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
620 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
621 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
622 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
623 return Either.right(responseFormat);
626 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
628 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
629 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
630 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
631 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
632 return Either.right(responseFormat);
635 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
636 grouping.setNormalizedName(normalizedName);
638 // Uniqueness under this category
639 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
640 if (groupingUniqueForSubCategory.isRight()) {
641 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
642 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
643 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
644 return Either.right(responseFormat);
647 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
648 if (!isGroupingUnique) {
649 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
650 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
651 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
652 return Either.right(responseFormat);
655 // Setting name of grouping to fit the similar grouping name ignoring
657 // For example if Network-->kUKU exists for service sub-category
658 // Network, and user is trying to create grouping Router-->Kuku for
659 // service sub-category Router,
660 // his grouping name will be Router-->kUKU.
661 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
662 if (groupingUniqueForType.isRight()) {
663 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
664 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
665 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
666 return Either.right(responseFormat);
668 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
669 if (groupingDefinition != null) {
670 groupingName = groupingDefinition.getName();
673 grouping.setName(groupingName);
674 ///////////////////////////////////////////// Validations end
676 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
677 if (createGrouping.isRight()) {
678 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
679 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
680 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
681 return Either.right(responseFormat);
684 GroupingDefinition groupingCreated = createGrouping.left().value();
685 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
686 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
687 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
688 return Either.left(groupingCreated);
691 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
692 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
693 ResponseFormat responseFormat;
694 User user = new User();
695 if (userId == null) {
696 user.setUserId("UNKNOWN");
697 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
698 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
699 return Either.right(responseFormat);
702 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "get All Categories", false);
703 if (validateUser.isRight()) {
704 user.setUserId(userId);
705 log.debug("Validation of user failed, userId {}", userId);
706 responseFormat = validateUser.right().value();
707 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
708 return Either.right(responseFormat);
710 user = validateUser.left().value();
712 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
713 if (componentTypeEnum == null) {
714 log.debug("Cannot create category for component type {}", componentType);
715 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
716 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
717 return Either.right(responseFormat);
720 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
721 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
722 if (getAllCategoriesByType.isRight()) {
723 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
724 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
725 return Either.right(responseFormat);
727 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
728 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
729 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
730 return Either.left(categories);
733 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
734 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
735 ResponseFormat responseFormat;
736 UiCategories categories = new UiCategories();
738 Either<User, ResponseFormat> userResponse = validateUserExists(userId, "get all categories", false);
740 if (userResponse.isRight()) {
741 return Either.right(userResponse.right().value());
743 User user = userResponse.left().value();
745 //GET resource categories
746 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
747 if (getResourceCategoriesByType.isRight()) {
748 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
749 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
750 return Either.right(responseFormat);
752 categories.setResourceCategories(getResourceCategoriesByType.left().value());
754 //GET service categories
755 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
756 if (getServiceCategoriesByType.isRight()) {
757 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
758 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
759 return Either.right(responseFormat);
761 categories.setServiceCategories(getServiceCategoriesByType.left().value());
763 //GET product categories
764 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
765 if (getProductCategoriesByType.isRight()) {
766 responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
767 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
768 return Either.right(responseFormat);
771 categories.setProductCategories(getProductCategoriesByType.left().value());
772 return Either.left(categories);
776 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
778 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Category", false);
779 if (resp.isRight()) {
780 return Either.right(resp.right().value());
783 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
784 if (componentTypeEnum == null) {
785 log.debug("Cannot create category for component type {}", componentTypeParamName);
786 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
789 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
791 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
792 if (deleteCategoryByType.isRight()) {
793 // auditing, logging here...
794 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
796 CategoryDefinition category = deleteCategoryByType.left().value();
797 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
798 return Either.left(category);
801 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String grandParentCategoryId, String parentSubCategoryId, String componentTypeParamName, String userId) {
803 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Sub Category", false);
804 if (resp.isRight()) {
805 return Either.right(resp.right().value());
808 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
809 if (componentTypeEnum == null) {
810 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
811 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
814 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
816 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
817 if (deleteSubCategoryByType.isRight()) {
818 // auditing, logging here...
819 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
821 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
822 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
823 return Either.left(subCategory);
826 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String grandParentCategoryId, String parentSubCategoryId, String groupingId, String componentTypeParamName, String userId) {
828 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Grouping", false);
829 if (resp.isRight()) {
830 return Either.right(resp.right().value());
833 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
834 if (componentTypeEnum == null) {
835 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
836 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
839 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
841 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
842 if (deleteGroupingByType.isRight()) {
843 // auditing, logging here...
844 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
846 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
847 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
848 return Either.left(deletedGrouping);
851 private Either<User, ResponseFormat> validateUser(String userId) {
853 // validate user exists
854 if (userId == null) {
855 log.debug("UserId is null");
856 return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
859 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
860 if (userResult.isRight()) {
861 ResponseFormat responseFormat;
862 if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
863 log.debug("Not authorized user, userId = {}", userId);
864 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
866 log.debug("Failed to authorize user, userId = {}", userId);
867 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
870 return Either.right(responseFormat);
872 return Either.left(userResult.left().value());
873 // ========================================-
876 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
877 String role = user.getRole();
878 boolean validAdminAction = (role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE));
879 boolean validProductAction = (role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT));
881 if (!(validAdminAction || validProductAction)) {
882 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
883 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
884 return Either.right(responseFormat);
886 return Either.left(true);
889 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
890 boolean validResourceAction = (componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY));
891 boolean validServiceAction = (componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY);
892 boolean validProductAction = (componentType == ComponentTypeEnum.PRODUCT); // can
898 if (!(validResourceAction || validServiceAction || validProductAction)) {
899 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
900 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
901 return Either.right(responseFormat);
903 return Either.left(true);
906 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
907 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
908 if (categoryByTypeAndId.isRight()) {
909 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
910 ActionStatus actionStatus = categoryByTypeAndId.right().value();
911 ResponseFormat responseFormat;
912 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
913 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
915 responseFormat = componentsUtils.getResponseFormat(actionStatus);
917 return Either.right(responseFormat);
919 return Either.left(categoryByTypeAndId.left().value());
922 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
923 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
924 if (subCategoryByTypeAndId.isRight()) {
925 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
926 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
927 ResponseFormat responseFormat;
928 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
929 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
931 responseFormat = componentsUtils.getResponseFormat(actionStatus);
933 return Either.right(responseFormat);
935 return Either.left(subCategoryByTypeAndId.left().value());
938 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
939 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
942 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
943 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
946 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
947 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
951 * New categories flow - end
954 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
955 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
956 if (resp.isRight()) {
957 return Either.right(resp.right().value());
959 return elementOperation.getAllTags();
962 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
963 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
964 if (resp.isRight()) {
965 return Either.right(resp.right().value());
967 return elementOperation.getAllPropertyScopes();
970 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
971 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
972 if (resp.isRight()) {
973 return Either.right(resp.right().value());
975 return elementOperation.getAllArtifactTypes();
978 public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
979 return elementOperation.getAllDeploymentArtifactTypes();
982 public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
983 return elementOperation.getDefaultHeatTimeout();
986 public Either<Map<String, List<? extends Component>>, ResponseFormat> getCatalogComponents(String userId) {
987 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Catalog Components", false);
988 if (resp.isRight()) {
989 return Either.right(resp.right().value());
991 Map<String, List<? extends Component>> resMap = new HashMap<>();
993 Either<List<Resource>, StorageOperationStatus> resResources = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.RESOURCE, true);
994 if (resResources.isLeft()) {
995 Either<List<Service>, StorageOperationStatus> resServices = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.SERVICE, true);
996 if (resServices.isLeft()) {
997 // Either<List<Product>, StorageOperationStatus> resProducts = productOperation.getProductCatalogData(false);
998 // if (resProducts.isLeft()) {
999 resMap.put("resources", resResources.left().value());
1000 resMap.put("services", resServices.left().value());
1001 resMap.put("products", new ArrayList<>());
1003 return Either.left(resMap);
1005 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resServices.right().value())));
1008 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resResources.right().value())));
1012 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1013 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1015 if (query != null) {
1016 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1017 if (invalidFilter.isPresent()) {
1018 log.debug("getFilteredAssetList: invalid filter key");
1019 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1023 if (filters == null || filters.isEmpty()) {
1024 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, false);
1025 if(componentsList.isRight()) {
1026 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1028 return Either.left(componentsList.left().value());
1031 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1033 if (result.isRight()) {// category hierarchy mismatch or
1034 // category/subCategory/distributionStatus not
1036 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1037 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1039 if (result.left().value().isEmpty()) {// no assets found for requested
1041 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1043 return Either.left(result.left().value());
1046 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1047 Either<List<Component>, StorageOperationStatus> assetResult = null;
1048 if(assetType == ComponentTypeEnum.RESOURCE){
1050 assetResult = getFilteredResouces(filters, inTransaction);
1052 } else if (assetType == ComponentTypeEnum.SERVICE){
1054 assetResult = getFilteredServices(filters, inTransaction);
1059 private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1061 Either<List<T>, StorageOperationStatus> components = null;
1063 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1064 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1065 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1066 if (distributionStatus != null && distEnum == null) {
1067 filters.remove(FilterKeyEnum.CATEGORY);
1068 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1071 if (categoryName != null) { // primary filter
1072 components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, GraphEdgeLabels.CATEGORY.getProperty(), NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1073 if (components.isLeft() && distEnum != null) {// secondary filter
1074 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1075 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1077 filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1081 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1082 distStatusSet.add(distEnum);
1083 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1084 if (servicesWithDistStatus.isRight()) { // not found == empty list
1085 return Either.left(new ArrayList<>());
1088 return Either.left((List<T>)servicesWithDistStatus.left().value());
1091 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1093 if (assetType == null || assetType == null) {
1094 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1095 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1098 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1100 if (assetTypeEnum == null) {
1101 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1102 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1105 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, null);
1106 if(componentsListByUuid.isRight()) {
1107 log.debug("getCatalogComponentsByUuidAndAssetType: Service fetching failed");
1108 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), ComponentTypeEnum.SERVICE);
1109 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1112 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + "Service fetching successful");
1113 return Either.left(componentsListByUuid.left().value());
1116 public List<String> getAllComponentTypesParamNames() {
1117 List<String> paramNames = new ArrayList<>();
1118 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1119 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1120 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1124 public List<String> getAllSupportedRoles() {
1125 Role[] values = Role.values();
1126 List<String> roleNames = new ArrayList<>();
1127 for (Role role : values) {
1128 roleNames.add(role.name());
1133 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1134 return elementOperation.getResourceTypesMap();
1137 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1138 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1139 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1140 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1141 return params.stream().filter(noMatch).findAny();
1144 private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1145 List<String> params = new ArrayList<String>();
1146 if (1 == filters.size()) {
1147 params.add(assetType.getValue().toLowerCase());
1148 params.add(filters.keySet().iterator().next().getName());
1149 params.add(filters.values().iterator().next());
1151 params.add(assetType.getValue());
1152 params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1153 params.add(filters.get(FilterKeyEnum.CATEGORY));
1158 public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1160 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1161 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1162 ResourceTypeEnum resourceType = ResourceTypeEnum.getType( filters.get(FilterKeyEnum.RESOURCE_TYPE));
1163 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1164 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1166 if (categoryName != null) {
1167 subcategories = getAllSubCategories(categoryName);
1168 if (subcategories.isRight()) {
1169 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1170 return Either.right(subcategories.right().value());
1173 if (subCategoryName != null) { // primary filter
1174 if (categoryName != null) {
1175 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1176 if (!subCategoryData.isPresent()) {
1177 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1179 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction,
1180 ResourceMetadataData.class, resourceType);
1183 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1185 if(subcategories != null){
1186 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1188 return fetchByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1191 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1192 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1193 if (categoryResult.isRight()) {
1194 return Either.right(categoryResult.right().value());
1196 CategoryData categoryData = categoryResult.left().value();
1198 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1199 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1200 if (childrenNodes.isRight()) {
1201 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1203 return Either.left(childrenNodes.left().value());
1206 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1207 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1208 return childNodes.stream().filter(matchName).findAny();
1211 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1212 Class<S> clazz, ResourceTypeEnum resourceType) {
1214 Either<TitanGraph, TitanOperationStatus> graph = titanDao.getGraph();
1215 if (graph.isRight()) {
1216 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(graph.right().value()));
1219 return collectComponents(graph.left().value(), neededType, categoryUid, categoryType, clazz, resourceType);
1222 if (false == inTransaction) {
1228 protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1229 Class<S> clazz, ResourceTypeEnum resourceType) {
1230 List<T> components = new ArrayList<>();
1232 Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1233 Map<String, Object> props = new HashMap<String, Object>();
1234 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1235 Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1236 if (getCategory.isRight()) {
1237 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1239 Either<TitanGraph, TitanOperationStatus> graph = titanDao.getGraph();
1240 if (graph.isRight()) {
1241 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(graph.right().value()));
1244 for (GraphNode category : getCategory.left().value()) {
1245 Either<List<T>, StorageOperationStatus> result = collectComponents(graph.left().value(), neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1246 if (result.isRight()) {
1249 components.addAll(result.left().value());
1252 return Either.left(components);
1254 if (false == inTransaction) {
1260 private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(TitanGraph graph, NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1261 List<T> components = new ArrayList<>();
1262 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1263 if (parentNodes.isLeft()) {
1264 for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1265 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1266 Boolean isHighest = componentData.isHighestVersion();
1267 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1269 if (isHighest && isMatchingResourceType) {
1270 Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1271 if (result.isRight()) {
1272 return Either.right(result.right().value());
1274 components.add(result.left().value());
1278 return Either.left(components);
1281 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType,
1282 ComponentMetadataDataDefinition componentData) {
1285 if (componentType == NodeTypeEnum.Resource) {
1286 if (resourceType == null) {
1289 isMatching = resourceType == ((ResourceMetadataDataDefinition)componentData).getResourceType();
1297 private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1298 List<T> components = new ArrayList<>();
1300 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1301 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource,
1302 inTransaction, ResourceMetadataData.class, resourceType);
1303 if (fetched.isRight()) {
1307 components.addAll(fetched.left().value());
1309 return Either.left(components);
1312 private Either<List<Component>, StorageOperationStatus> fetchByResourceType(String resourceType, boolean inTransaction) {
1313 List<Component> components = null;
1314 StorageOperationStatus status;
1315 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1316 Either<List<Component>, StorageOperationStatus> result;
1319 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchByResourceType(resourceType); //titanGenericDao.getByCriteria(nodeType, props, clazz);
1320 if (getResources.isRight()) {
1321 status = getResources.right().value();
1322 if(status != StorageOperationStatus.NOT_FOUND){
1323 statusWrapper.setInnerElement(getResources.right().value());
1325 components = new ArrayList<>();
1328 components = getResources.left().value();
1330 if(!statusWrapper.isEmpty()){
1331 result = Either.right(statusWrapper.getInnerElement());
1333 result = Either.left(components);
1337 if (!inTransaction) {
1343 Component convertComponentMetadataDataToComponent(ComponentMetadataData componentMetadataData) {
1344 return convertResourceDataToResource((ResourceMetadataData) componentMetadataData);
1346 private Resource convertResourceDataToResource(ResourceMetadataData resourceData) {
1348 ResourceMetadataDefinition resourceMetadataDataDefinition = new ResourceMetadataDefinition((ResourceMetadataDataDefinition) resourceData.getMetadataDataDefinition());
1350 Resource resource = new Resource(resourceMetadataDataDefinition);
1354 private <T> Either<List<T>, StorageOperationStatus> fetchByDistributionStatus(String status, boolean inTransaction) {
1355 Map<String, Object> props = new HashMap<String, Object>();
1356 props.put(GraphPropertiesDictionary.DISTRIBUTION_STATUS.getProperty(), status);
1357 props.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true);
1358 return (Either<List<T>, StorageOperationStatus>) (Either<?, StorageOperationStatus>) getServiceListByCriteria(props, inTransaction);
1361 private Either<List<Service>, StorageOperationStatus> getServiceListByCriteria(Map<String, Object> props, boolean inTransaction) {
1362 props.put(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.Service.getName());
1363 Either<List<ServiceMetadataData>, TitanOperationStatus> byCriteria = titanGenericDao.getByCriteria(NodeTypeEnum.Service, props, ServiceMetadataData.class);
1365 if (byCriteria.isRight()) {
1366 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
1368 List<Service> services = new ArrayList<Service>();
1369 List<ServiceMetadataData> servicesDataList = byCriteria.left().value();
1370 for (ServiceMetadataData data : servicesDataList) {
1371 Either<Component, StorageOperationStatus> service = toscaOperationFacade.getToscaElement(data.getMetadataDataDefinition().getUniqueId());
1372 if (service.isLeft()) {
1373 services.add((Service)service.left().value());
1375 log.debug("Failed to fetch resource for name = {} and id = {}",data.getMetadataDataDefinition().getName(),data.getUniqueId());
1378 return Either.left(services);