Initial OpenECOMP SDC commit
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ElementBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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  */
20
21 package org.openecomp.sdc.be.components.impl;
22
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;
28 import java.util.Map;
29 import java.util.Optional;
30 import java.util.Set;
31 import java.util.function.Predicate;
32
33 import org.apache.http.NameValuePair;
34 import org.apache.http.client.utils.URLEncodedUtils;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
37 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
38 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
39 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
41 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
42 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
43 import org.openecomp.sdc.be.impl.ComponentsUtils;
44 import org.openecomp.sdc.be.model.ArtifactType;
45 import org.openecomp.sdc.be.model.Component;
46 import org.openecomp.sdc.be.model.DistributionStatusEnum;
47 import org.openecomp.sdc.be.model.LifecycleStateEnum;
48 import org.openecomp.sdc.be.model.Product;
49 import org.openecomp.sdc.be.model.PropertyScope;
50 import org.openecomp.sdc.be.model.Resource;
51 import org.openecomp.sdc.be.model.Service;
52 import org.openecomp.sdc.be.model.Tag;
53 import org.openecomp.sdc.be.model.User;
54 import org.openecomp.sdc.be.model.category.CategoryDefinition;
55 import org.openecomp.sdc.be.model.category.GroupingDefinition;
56 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
57 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
58 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
59 import org.openecomp.sdc.be.model.operations.impl.ComponentOperation;
60 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
61 import org.openecomp.sdc.be.user.Role;
62 import org.openecomp.sdc.be.user.UserBusinessLogic;
63 import org.openecomp.sdc.common.util.ValidationUtils;
64 import org.openecomp.sdc.exception.ResponseFormat;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68 import fj.data.Either;
69
70 @org.springframework.stereotype.Component("elementsBusinessLogic")
71 public class ElementBusinessLogic extends BaseBusinessLogic {
72
73         private static Logger log = LoggerFactory.getLogger(ElementBusinessLogic.class.getName());
74
75         @javax.annotation.Resource
76         private IElementOperation elementOperation;
77
78         @javax.annotation.Resource
79         private ComponentsUtils componentsUtils;
80
81         @javax.annotation.Resource
82         private UserBusinessLogic userAdminManager;
83
84         /**
85          * 
86          * @param user
87          * @return
88          */
89         public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
90                 Either<Map<String, List<? extends Component>>, ResponseFormat> response = null;
91                 // Getting the role
92                 String role = user.getRole();
93                 String userId = null;
94                 Role currentRole = Role.valueOf(role);
95
96                 switch (currentRole) {
97                 case DESIGNER:
98                         userId = user.getUserId();
99                         response = handleDesigner(userId);
100                         break;
101
102                 case TESTER:
103                         userId = user.getUserId();
104                         response = handleTester(userId);
105                         break;
106
107                 case GOVERNOR:
108                         userId = user.getUserId();
109                         response = handleGovernor(userId);
110                         break;
111
112                 case OPS:
113                         userId = user.getUserId();
114                         response = handleOps(userId);
115                         break;
116
117                 case PRODUCT_STRATEGIST:
118                         userId = user.getUserId();
119                         response = handleProductStrategist(userId);
120                         break;
121
122                 case PRODUCT_MANAGER:
123                         userId = user.getUserId();
124                         response = handleProductManager(userId);
125                         break;
126
127                 case ADMIN:
128                         response = handleAdmin();
129                         break;
130
131                 default:
132                         response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
133                         break;
134                 }
135                 return response;
136
137         }
138
139         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleAdmin() {
140                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
141                 // userId should stay null
142                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
143                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
144                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
145                 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
146                 return response;
147         }
148
149         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
150                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
151                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
152                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
153                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
154                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
155                 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
156                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
157                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
158                 // more states
159                 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
160                 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
161                 return response;
162         }
163
164         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleGovernor(String userId) {
165                 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(null);
166                 return result;
167         }
168
169         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductStrategist(String userId) {
170                 // Should be empty list according to Ella, 13/03/16
171                 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
172                 result.put("products", new ArrayList<>());
173                 return Either.left(result);
174         }
175
176         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
177                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
178                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
179                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
180                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
181                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
182                 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
183                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
184                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
185                 // more states
186                 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
187                 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
188                 return response;
189         }
190
191         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleOps(String userId) {
192                 Set<DistributionStatusEnum> distStatus = new HashSet<DistributionStatusEnum>();
193                 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
194                 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
195
196                 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(distStatus);
197                 return result;
198         }
199
200         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
201                 Map<String, Object> propertiesToMatch = new HashMap<>();
202                 propertiesToMatch.put(GraphPropertiesDictionary.STATE.getProperty(), LifecycleStateEnum.CERTIFIED.name());
203
204                 Either<Set<Service>, StorageOperationStatus> services = serviceOperation.getCertifiedServicesWithDistStatus(propertiesToMatch, distStatus, false);
205                 if (services.isLeft()) {
206                         Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
207                         List<Service> list = new ArrayList<>();
208                         list.addAll(services.left().value());
209                         result.put("services", list);
210                         return Either.left(result);
211                 } else {
212                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
213                 }
214         }
215
216         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleTester(String userId) {
217                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
218                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
219                 Either<List<Resource>, StorageOperationStatus> resources = resourceOperation.getTesterFollowed(userId, lifecycleStates, false);
220
221                 if (resources.isLeft()) {
222                         Either<List<Service>, StorageOperationStatus> services = serviceOperation.getTesterFollowed(userId, lifecycleStates, false);
223                         if (services.isLeft()) {
224                                 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
225                                 result.put("services", services.left().value());
226                                 result.put("resources", resources.left().value());
227                                 return Either.left(result);
228                         } else {
229                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
230                         }
231                 } else {
232                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
233                 }
234         }
235
236         private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
237                 Either<List<Resource>, StorageOperationStatus> resources = resourceOperation.getFollowed(userId, lifecycleStates, lastStateStates, false);
238
239                 if (resources.isLeft()) {
240                         Either<List<Service>, StorageOperationStatus> services = serviceOperation.getFollowed(userId, lifecycleStates, lastStateStates, false);
241                         if (services.isLeft()) {
242                                 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
243                                 result.put("services", services.left().value());
244                                 result.put("resources", resources.left().value());
245                                 return Either.left(result);
246                         } else {
247                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
248                         }
249                 } else {
250                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
251                 }
252         }
253
254         private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
255                 Either<List<Product>, StorageOperationStatus> products = productOperation.getFollowed(userId, lifecycleStates, lastStateStates, false);
256                 if (products.isLeft()) {
257                         Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
258                         result.put("products", products.left().value());
259                         return Either.left(result);
260                 } else {
261                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
262                 }
263         }
264
265         /*
266          * New categories flow - start
267          */
268         public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
269                 return elementOperation.getAllResourceCategories();
270         }
271
272         public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
273                 return elementOperation.getAllServiceCategories();
274         }
275
276         public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
277
278                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
279                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
280                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
281                 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
282
283                 User user = new User();
284                 Either<User, ResponseFormat> validateUser = validateUser(userId);
285                 if (validateUser.isRight()) {
286                         log.debug("Validation of user failed, userId {}", userId);
287                         ResponseFormat responseFormat = validateUser.right().value();
288                         user = new User();
289                         user.setUserId(userId);
290                         String currCategoryName = (category == null ? null : category.getName());
291                         handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
292                         return Either.right(responseFormat);
293                 }
294
295                 user = validateUser.left().value();
296
297                 if (category == null) {
298                         log.debug("Category json is invalid");
299                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
300                         handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
301                         return Either.right(responseFormat);
302                 }
303
304                 String categoryName = category.getName();
305                 // For auditing of failures we need the original non-normalized name
306                 String origCategoryName = categoryName;
307                 if (componentTypeEnum == null) {
308                         log.debug("Component type {} is invalid", componentTypeParamName);
309                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
310                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
311                         return Either.right(responseFormat);
312                 }
313
314                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
315                 if (validateUserRole.isRight()) {
316                         log.debug("Validation of user role failed, userId {}", userId);
317                         ResponseFormat responseFormat = validateUserRole.right().value();
318                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
319                         return Either.right(responseFormat);
320                 }
321
322                 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
323                         log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
324                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
325                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
326                         return Either.right(responseFormat);
327                 }
328
329                 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
330
331                 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
332                         log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
333                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
334                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
335                         return Either.right(responseFormat);
336                 }
337
338                 category.setName(categoryName);
339
340                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
341                 category.setNormalizedName(normalizedName);
342
343                 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
344
345                 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
346                 if (categoryUniqueEither.isRight()) {
347                         log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
348                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
349                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
350                         return Either.right(responseFormat);
351                 }
352
353                 Boolean isCategoryUnique = categoryUniqueEither.left().value();
354                 if (!isCategoryUnique) {
355                         log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
356                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
357                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
358                         return Either.right(responseFormat);
359                 }
360
361                 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
362                 if (createCategoryByType.isRight()) {
363                         log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
364                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
365                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
366                         return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
367                 }
368                 category = createCategoryByType.left().value();
369                 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
370                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
371                 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
372                 return Either.left(category);
373         }
374
375         public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
376
377                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
378                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
379                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
380                 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
381                 // For auditing
382                 String parentCategoryName = parentCategoryId;
383
384                 if (subCategory == null) {
385                         log.debug("Sub-category json is invalid");
386                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
387                         handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
388                         return Either.right(responseFormat);
389                 }
390
391                 String subCategoryName = subCategory.getName();
392                 // For auditing of failures we need the original non-normalized name
393                 String origSubCategoryName = subCategoryName;
394
395                 User user = new User();
396                 /*
397                  * if (userId == null) { user.setUserId("UNKNOWN"); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION); handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName,
398                  * auditingAction, componentType); return Either.right(responseFormat); }
399                  */
400                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "createSubCategory", false);
401                 if (validateUser.isRight()) {
402                         log.debug("Validation of user failed, userId {}", userId);
403                         ResponseFormat responseFormat = validateUser.right().value();
404                         user = new User();
405                         user.setUserId(userId);
406                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
407                         return Either.right(responseFormat);
408                 }
409
410                 user = validateUser.left().value();
411
412                 if (componentTypeEnum == null) {
413                         log.debug("Component type {} is invalid", componentTypeParamName);
414                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
415                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
416                         return Either.right(responseFormat);
417                 }
418
419                 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
420                 if (validateComponentType.isRight()) {
421                         log.debug("Validation of component type for sub-category failed");
422                         ResponseFormat responseFormat = validateComponentType.right().value();
423                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
424                         return Either.right(responseFormat);
425                 }
426
427                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
428                 if (validateUserRole.isRight()) {
429                         log.debug("Validation of user role failed, userId {}", userId);
430                         ResponseFormat responseFormat = validateUserRole.right().value();
431                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
432                         return Either.right(responseFormat);
433                 }
434
435                 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
436                 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
437
438                 CategoryDefinition categoryDefinition;
439                 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
440                 if (validateCategoryExists.isRight()) {
441                         log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
442                         ResponseFormat responseFormat = validateCategoryExists.right().value();
443                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
444                         return Either.right(responseFormat);
445                 }
446
447                 categoryDefinition = validateCategoryExists.left().value();
448                 parentCategoryName = categoryDefinition.getName();
449
450                 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
451                         log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
452                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
453                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
454                         return Either.right(responseFormat);
455                 }
456
457                 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
458
459                 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
460                         log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
461                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
462                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
463                         return Either.right(responseFormat);
464                 }
465
466                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
467                 subCategory.setNormalizedName(normalizedName);
468
469                 // Uniqueness under this category
470                 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
471                 if (subCategoryUniqueForCategory.isRight()) {
472                         log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
473                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
474                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
475                         return Either.right(responseFormat);
476                 }
477
478                 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
479                 if (!isSubUnique) {
480                         log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
481                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
482                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
483                         return Either.right(responseFormat);
484                 }
485
486                 // Setting name of subcategory to fit the similar subcategory name
487                 // ignoring cases.
488                 // For example if Network-->kUKU exists for service category Network,
489                 // and user is trying to create Router-->Kuku for service category
490                 // Router,
491                 // his subcategory name will be Router-->kUKU.
492                 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
493                 if (subCategoryUniqueForType.isRight()) {
494                         log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
495                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
496                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
497                         return Either.right(responseFormat);
498                 }
499                 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
500                 if (subCategoryDefinition != null) {
501                         subCategoryName = subCategoryDefinition.getName();
502                 }
503
504                 subCategory.setName(subCategoryName);
505                 ///////////////////////////////////////////// Validations end
506
507                 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
508                 if (createSubCategory.isRight()) {
509                         log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
510                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
511                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
512                         return Either.right(responseFormat);
513                 }
514
515                 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
516                 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
517                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
518                 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
519                 return Either.left(subCategoryCreated);
520         }
521
522         public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
523
524                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
525                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
526                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
527                 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
528                 // For auditing
529                 String parentCategoryName = grandParentCategoryId;
530                 String parentSubCategoryName = parentSubCategoryId;
531
532                 User user;
533                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "create Grouping", false);
534                 if (validateUser.isRight()) {
535                         log.debug("Validation of user failed, userId {}", userId);
536                         ResponseFormat responseFormat = validateUser.right().value();
537                         user = new User();
538                         user.setUserId(userId);
539                         String groupingNameForAudit = (grouping == null ? null : grouping.getName());
540                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
541                         return Either.right(responseFormat);
542                 }
543
544                 user = validateUser.left().value();
545
546                 if (grouping == null) {
547                         log.debug("Grouping json is invalid");
548                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
549                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
550                         return Either.right(responseFormat);
551                 }
552
553                 String groupingName = grouping.getName();
554                 // For auditing of failures we need the original non-normalized name
555                 String origGroupingName = groupingName;
556
557                 if (componentTypeEnum == null) {
558                         log.debug("Component type {} is invalid", componentTypeParamName);
559                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
560                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
561                         return Either.right(responseFormat);
562                 }
563
564                 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
565                 if (validateComponentType.isRight()) {
566                         log.debug("Validation of component type for grouping failed");
567                         ResponseFormat responseFormat = validateComponentType.right().value();
568                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
569                         return Either.right(responseFormat);
570                 }
571
572                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
573                 if (validateUserRole.isRight()) {
574                         log.debug("Validation of user role failed, userId {}", userId);
575                         ResponseFormat responseFormat = validateUserRole.right().value();
576                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
577                         return Either.right(responseFormat);
578                 }
579
580                 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
581                 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
582                 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
583
584                 // Validate category
585                 CategoryDefinition categoryDefinition;
586                 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
587                 if (validateCategoryExists.isRight()) {
588                         log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
589                         ResponseFormat responseFormat = validateCategoryExists.right().value();
590                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
591                         return Either.right(responseFormat);
592                 }
593
594                 categoryDefinition = validateCategoryExists.left().value();
595                 parentCategoryName = categoryDefinition.getName();
596
597                 // Validate subcategory
598                 SubCategoryDefinition subCategoryDefinition;
599                 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
600                 if (validateSubCategoryExists.isRight()) {
601                         log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
602                         ResponseFormat responseFormat = validateSubCategoryExists.right().value();
603                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
604                         return Either.right(responseFormat);
605                 }
606
607                 subCategoryDefinition = validateSubCategoryExists.left().value();
608                 parentSubCategoryName = subCategoryDefinition.getName();
609
610                 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
611                         log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
612                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
613                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
614                         return Either.right(responseFormat);
615                 }
616
617                 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
618
619                 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
620                         log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
621                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
622                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
623                         return Either.right(responseFormat);
624                 }
625
626                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
627                 grouping.setNormalizedName(normalizedName);
628
629                 // Uniqueness under this category
630                 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
631                 if (groupingUniqueForSubCategory.isRight()) {
632                         log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
633                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
634                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
635                         return Either.right(responseFormat);
636                 }
637
638                 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
639                 if (!isGroupingUnique) {
640                         log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
641                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
642                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
643                         return Either.right(responseFormat);
644                 }
645
646                 // Setting name of grouping to fit the similar grouping name ignoring
647                 // cases.
648                 // For example if Network-->kUKU exists for service sub-category
649                 // Network, and user is trying to create grouping Router-->Kuku for
650                 // service sub-category Router,
651                 // his grouping name will be Router-->kUKU.
652                 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
653                 if (groupingUniqueForType.isRight()) {
654                         log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
655                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
656                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
657                         return Either.right(responseFormat);
658                 }
659                 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
660                 if (groupingDefinition != null) {
661                         groupingName = groupingDefinition.getName();
662                 }
663
664                 grouping.setName(groupingName);
665                 ///////////////////////////////////////////// Validations end
666
667                 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
668                 if (createGrouping.isRight()) {
669                         log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
670                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
671                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
672                         return Either.right(responseFormat);
673                 }
674
675                 GroupingDefinition groupingCreated = createGrouping.left().value();
676                 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
677                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
678                 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
679                 return Either.left(groupingCreated);
680         }
681
682         public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
683                 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
684                 ResponseFormat responseFormat;
685                 User user = new User();
686                 if (userId == null) {
687                         user.setUserId("UNKNOWN");
688                         responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
689                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
690                         return Either.right(responseFormat);
691                 }
692
693                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "get All Categories", false);
694                 if (validateUser.isRight()) {
695                         user.setUserId(userId);
696                         log.debug("Validation of user failed, userId {}", userId);
697                         responseFormat = validateUser.right().value();
698                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
699                         return Either.right(responseFormat);
700                 }
701                 user = validateUser.left().value();
702
703                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
704                 if (componentTypeEnum == null) {
705                         log.debug("Cannot create category for component type {}", componentType);
706                         responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
707                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
708                         return Either.right(responseFormat);
709                 }
710
711                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
712                 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
713                 if (getAllCategoriesByType.isRight()) {
714                         responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
715                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
716                         return Either.right(responseFormat);
717                 }
718                 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
719                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
720                 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
721                 return Either.left(categories);
722         }
723
724         public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
725
726                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Category", false);
727                 if (resp.isRight()) {
728                         return Either.right(resp.right().value());
729                 }
730
731                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
732                 if (componentTypeEnum == null) {
733                         log.debug("Cannot create category for component type {}", componentTypeParamName);
734                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
735                 }
736
737                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
738
739                 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
740                 if (deleteCategoryByType.isRight()) {
741                         // auditing, logging here...
742                         return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
743                 }
744                 CategoryDefinition category = deleteCategoryByType.left().value();
745                 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
746                 return Either.left(category);
747         }
748
749         public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String grandParentCategoryId, String parentSubCategoryId, String componentTypeParamName, String userId) {
750
751                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Sub Category", false);
752                 if (resp.isRight()) {
753                         return Either.right(resp.right().value());
754                 }
755
756                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
757                 if (componentTypeEnum == null) {
758                         log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
759                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
760                 }
761
762                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
763
764                 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
765                 if (deleteSubCategoryByType.isRight()) {
766                         // auditing, logging here...
767                         return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
768                 }
769                 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
770                 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
771                 return Either.left(subCategory);
772         }
773
774         public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String grandParentCategoryId, String parentSubCategoryId, String groupingId, String componentTypeParamName, String userId) {
775
776                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Grouping", false);
777                 if (resp.isRight()) {
778                         return Either.right(resp.right().value());
779                 }
780
781                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
782                 if (componentTypeEnum == null) {
783                         log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
784                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
785                 }
786
787                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
788
789                 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
790                 if (deleteGroupingByType.isRight()) {
791                         // auditing, logging here...
792                         return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
793                 }
794                 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
795                 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
796                 return Either.left(deletedGrouping);
797         }
798
799         private Either<User, ResponseFormat> validateUser(String userId) {
800
801                 // validate user exists
802                 if (userId == null) {
803                         log.debug("User id is null");
804                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
805                 }
806
807                 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
808                 if (userResult.isRight()) {
809                         ResponseFormat responseFormat;
810                         if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
811                                 log.debug("Not authorized user, userId = {}", userId);
812                                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
813                         } else {
814                                 log.debug("Failed to authorize user, userId = {}", userId);
815                                 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
816                         }
817
818                         return Either.right(responseFormat);
819                 }
820                 return Either.left(userResult.left().value());
821                 // ========================================-
822         }
823
824         private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
825                 String role = user.getRole();
826                 boolean validAdminAction = (role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE));
827                 boolean validProductAction = (role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT));
828
829                 if (!(validAdminAction || validProductAction)) {
830                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
831                         log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
832                         return Either.right(responseFormat);
833                 }
834                 return Either.left(true);
835         }
836
837         private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
838                 boolean validResourceAction = (componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY));
839                 boolean validServiceAction = (componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY);
840                 boolean validProductAction = (componentType == ComponentTypeEnum.PRODUCT); // can
841                                                                                                                                                                         // be
842                                                                                                                                                                         // any
843                                                                                                                                                                         // category
844                                                                                                                                                                         // type
845
846                 if (!(validResourceAction || validServiceAction || validProductAction)) {
847                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
848                         log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
849                         return Either.right(responseFormat);
850                 }
851                 return Either.left(true);
852         }
853
854         private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
855                 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
856                 if (categoryByTypeAndId.isRight()) {
857                         log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
858                         ActionStatus actionStatus = categoryByTypeAndId.right().value();
859                         ResponseFormat responseFormat;
860                         if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
861                                 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
862                         } else {
863                                 responseFormat = componentsUtils.getResponseFormat(actionStatus);
864                         }
865                         return Either.right(responseFormat);
866                 }
867                 return Either.left(categoryByTypeAndId.left().value());
868         }
869
870         private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
871                 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
872                 if (subCategoryByTypeAndId.isRight()) {
873                         log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
874                         ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
875                         ResponseFormat responseFormat;
876                         if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
877                                 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
878                         } else {
879                                 responseFormat = componentsUtils.getResponseFormat(actionStatus);
880                         }
881                         return Either.right(responseFormat);
882                 }
883                 return Either.left(subCategoryByTypeAndId.left().value());
884         }
885
886         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
887                 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
888         }
889
890         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
891                 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
892         }
893
894         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
895                 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
896         }
897
898         /*
899          * New categories flow - end
900          */
901
902         public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
903                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
904                 if (resp.isRight()) {
905                         return Either.right(resp.right().value());
906                 }
907                 return elementOperation.getAllTags();
908         }
909
910         public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
911                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
912                 if (resp.isRight()) {
913                         return Either.right(resp.right().value());
914                 }
915                 return elementOperation.getAllPropertyScopes();
916         }
917
918         public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
919                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
920                 if (resp.isRight()) {
921                         return Either.right(resp.right().value());
922                 }
923                 return elementOperation.getAllArtifactTypes();
924         }
925
926         public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
927                 return elementOperation.getAllDeploymentArtifactTypes();
928         }
929
930         public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
931                 return elementOperation.getDefaultHeatTimeout();
932         }
933
934         public Either<Map<String, List<? extends Component>>, ResponseFormat> getCatalogComponents(String userId) {
935                 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Catalog Components", false);
936                 if (resp.isRight()) {
937                         return Either.right(resp.right().value());
938                 }
939                 Map<String, List<? extends Component>> resMap = new HashMap<>();
940
941                 Either<List<Resource>, StorageOperationStatus> resResources = resourceOperation.getResourceCatalogData(false);
942                 if (resResources.isLeft()) {
943                         Either<List<Service>, StorageOperationStatus> resServices = serviceOperation.getServiceCatalogData(false);
944                         if (resServices.isLeft()) {
945                                 Either<List<Product>, StorageOperationStatus> resProducts = productOperation.getProductCatalogData(false);
946                                 if (resProducts.isLeft()) {
947                                         resMap.put("resources", resResources.left().value());
948                                         resMap.put("services", resServices.left().value());
949                                         resMap.put("products", resProducts.left().value());
950                                         return Either.left(resMap);
951                                 } else {
952                                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resProducts.right().value())));
953                                 }
954                         } else {
955                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resServices.right().value())));
956                         }
957                 } else {
958                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resResources.right().value())));
959                 }
960         }
961
962         public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
963                 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
964
965                 if (query != null) {
966                         Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
967                         if (invalidFilter.isPresent()) {
968                                 log.debug("getFilteredAssetList: invalid filter key");
969                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
970                         }
971                 }
972
973                 if (filters == null || filters.isEmpty()) {
974                         return getCatalogComponentsByAssetType(assetTypeEnum);
975                 }
976
977                 ComponentOperation componentOperation = getComponentOperation(assetTypeEnum);
978                 Either<List<Component>, StorageOperationStatus> result = componentOperation.getFilteredComponents(filters, false);
979
980                 if (result.isRight()) {// category hierarchy mismatch or
981                                                                 // category/subCategory/distributionStatus not
982                                                                 // found
983                         List<String> params = getErrorResponseParams(filters, assetTypeEnum);
984                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
985                 }
986                 if (result.left().value().isEmpty()) {// no assets found for requested
987                                                                                                 // criteria
988                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
989                 }
990                 return Either.left(result.left().value());
991         }
992
993         public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByAssetType(ComponentTypeEnum assetTypeEnum) {
994
995                 if (assetTypeEnum == null) {
996                         log.debug("getCatalogComponentsByAssetType: Corresponding ComponentTypeEnum not found");
997                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
998                 }
999
1000                 switch (assetTypeEnum) {
1001                 case RESOURCE:
1002
1003                         Either<List<Resource>, StorageOperationStatus> resourceCatalogData = resourceOperation.getResourceCatalogDataVFLatestCertifiedAndNonCertified(false);
1004                         if (resourceCatalogData.isLeft()) {
1005                                 log.debug("getCatalogComponentsByAssetType: Resource fetching successful");
1006                                 return Either.left(resourceCatalogData.left().value());
1007                         } else {
1008                                 log.debug("getCatalogComponentsByAssetType: Resource fetching failed");
1009                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resourceCatalogData.right().value())));
1010                         }
1011
1012                 case SERVICE:
1013                         Either<List<Service>, StorageOperationStatus> serviceCatalogData = serviceOperation.getServiceCatalogDataLatestCertifiedAndNotCertified(false);
1014                         if (serviceCatalogData.isLeft()) {
1015                                 log.debug("getCatalogComponentsByAssetType: Service fetching successful");
1016                                 return Either.left(serviceCatalogData.left().value());
1017                         } else {
1018                                 log.debug("getCatalogComponentsByAssetType: Service fetching failed");
1019                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceCatalogData.right().value())));
1020                         }
1021                         /*
1022                          * case PRODUCT: Either<List<Product>, StorageOperationStatus> resCatalogData = productOperation.getProductCatalogData(false); if(resCatalogData.isLeft()){ log. debug("getCatalogComponentsByAssetType: Product fetching successful" );
1023                          * return Either.left(resCatalogData.left().value()); }else { log. debug("getCatalogComponentsByAssetType: Product fetching failed" ); return Either.right(componentsUtils .getResponseFormat(componentsUtils.convertFromStorageResponse(
1024                          * resCatalogData.right().value()))); }
1025                          */
1026                 default:
1027                         log.debug("Invalid Asset Type");
1028                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1029                 }
1030         }
1031
1032         // TODO new story Tal
1033         public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1034
1035                 if (assetType == null || assetType == null) {
1036                         log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1037                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1038                 }
1039
1040                 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1041
1042                 if (assetTypeEnum == null) {
1043                         log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1044                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1045                 }
1046
1047                 switch (assetTypeEnum) {
1048
1049                 case RESOURCE:
1050                         Either<List<Resource>, StorageOperationStatus> resourceListByUuid = resourceOperation.getLatestResourceByUuid(uuid, false);
1051
1052                         if (resourceListByUuid.isLeft()) {
1053                                 log.debug("getCatalogComponentsByUuidAndAssetType: Resource fetching successful");
1054                                 return Either.left(resourceListByUuid.left().value());
1055                         }
1056
1057                         ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(resourceListByUuid.right().value());
1058                         log.debug("getCatalogComponentsByUuidAndAssetType: Resource fetching failed");
1059                         return Either.right(componentsUtils.getResponseFormat(actionStatus));
1060
1061                 case SERVICE:
1062                         Either<List<Service>, StorageOperationStatus> serviceCatalogData = serviceOperation.getLatestServiceByUuid(uuid, false);
1063
1064                         if (serviceCatalogData.isLeft()) {
1065                                 log.debug("getCatalogComponentsByUuidAndAssetType: Service fetching successful");
1066                                 return Either.left(serviceCatalogData.left().value());
1067                         }
1068
1069                         log.debug("getCatalogComponentsByUuidAndAssetType: Service fetching failed");
1070                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceCatalogData.right().value())));
1071                 // case Product is for future US
1072                 /*
1073                  * case PRODUCT: Either<List<Product>, StorageOperationStatus> resCatalogData = productOperation.getProductCatalogData(false); if(resCatalogData.isLeft()){ log. debug("getCatalogComponentsByAssetType: Product fetching successful" ); return
1074                  * Either.left(resCatalogData.left().value()); }else { log. debug("getCatalogComponentsByAssetType: Product fetching failed" ); return Either.right(componentsUtils .getResponseFormat(componentsUtils.convertFromStorageResponse(
1075                  * resCatalogData.right().value()))); }
1076                  */
1077                 default:
1078                         log.debug("Invalid Asset Type");
1079                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1080                 }
1081         }
1082
1083         public List<String> getAllComponentTypesParamNames() {
1084                 List<String> paramNames = new ArrayList<>();
1085                 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1086                 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1087                 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1088                 return paramNames;
1089         }
1090
1091         public List<String> getAllSupportedRoles() {
1092                 Role[] values = Role.values();
1093                 List<String> roleNames = new ArrayList<>();
1094                 for (Role role : values) {
1095                         roleNames.add(role.name());
1096                 }
1097                 return roleNames;
1098         }
1099
1100         public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1101                 return elementOperation.getResourceTypesMap();
1102         }
1103
1104         private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1105                 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1106                 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1107                 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1108                 return params.stream().filter(noMatch).findAny();
1109         }
1110
1111         private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1112                 List<String> params = new ArrayList<String>();
1113                 if (1 == filters.size()) {
1114                         params.add(assetType.getValue().toLowerCase());
1115                         params.add(filters.keySet().iterator().next().getName());
1116                         params.add(filters.values().iterator().next());
1117                 } else {
1118                         params.add(assetType.getValue());
1119                         params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1120                         params.add(filters.get(FilterKeyEnum.CATEGORY));
1121                 }
1122                 return params;
1123         }
1124
1125 }