Merge "[1707-OS] Updated license text according to the"
[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.EnumMap;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Set;
32 import java.util.function.Predicate;
33 import java.util.stream.Collectors;
34
35 import org.apache.commons.lang3.tuple.ImmutablePair;
36 import org.apache.http.NameValuePair;
37 import org.apache.http.client.utils.URLEncodedUtils;
38 import org.openecomp.sdc.be.dao.api.ActionStatus;
39 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
40 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
41 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
42 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
43 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
44 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
45 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
46 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
47 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
48 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
49 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
50 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
51 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
52 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
53 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
54 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
55 import org.openecomp.sdc.be.impl.ComponentsUtils;
56 import org.openecomp.sdc.be.model.ArtifactType;
57 import org.openecomp.sdc.be.model.Component;
58 import org.openecomp.sdc.be.model.DistributionStatusEnum;
59 import org.openecomp.sdc.be.model.LifecycleStateEnum;
60 import org.openecomp.sdc.be.model.Product;
61 import org.openecomp.sdc.be.model.PropertyScope;
62 import org.openecomp.sdc.be.model.Resource;
63 import org.openecomp.sdc.be.model.ResourceMetadataDefinition;
64 import org.openecomp.sdc.be.model.Service;
65 import org.openecomp.sdc.be.model.Tag;
66 import org.openecomp.sdc.be.model.User;
67 import org.openecomp.sdc.be.model.category.CategoryDefinition;
68 import org.openecomp.sdc.be.model.category.GroupingDefinition;
69 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
70 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
71 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
72 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
73 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
74 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
75 import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
76 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
77 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
78 import org.openecomp.sdc.be.resources.data.category.CategoryData;
79 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
80 import org.openecomp.sdc.be.ui.model.UiCategories;
81 import org.openecomp.sdc.be.user.Role;
82 import org.openecomp.sdc.be.user.UserBusinessLogic;
83 import org.openecomp.sdc.common.datastructure.Wrapper;
84 import org.openecomp.sdc.common.util.ValidationUtils;
85 import org.openecomp.sdc.exception.ResponseFormat;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88
89 import com.thinkaurelius.titan.core.TitanGraph;
90
91 import fj.data.Either;
92
93 @org.springframework.stereotype.Component("elementsBusinessLogic")
94 public class ElementBusinessLogic extends BaseBusinessLogic {
95
96         private static Logger log = LoggerFactory.getLogger(ElementBusinessLogic.class.getName());
97
98         @javax.annotation.Resource
99         private IElementOperation elementOperation;
100
101         @javax.annotation.Resource
102         private ComponentsUtils componentsUtils;
103
104         @javax.annotation.Resource
105         private UserBusinessLogic userAdminManager;
106
107         /**
108          * 
109          * @param user
110          * @return
111          */
112         public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
113                 Either<Map<String, List<? extends Component>>, ResponseFormat> response = null;
114                 // Getting the role
115                 String role = user.getRole();
116                 String userId = null;
117                 Role currentRole = Role.valueOf(role);
118
119                 switch (currentRole) {
120                 case DESIGNER:
121                         userId = user.getUserId();
122                         response = handleDesigner(userId);
123                         break;
124
125                 case TESTER:
126                         userId = user.getUserId();
127                         response = handleTester(userId);
128                         break;
129
130                 case GOVERNOR:
131                         userId = user.getUserId();
132                         response = handleGovernor(userId);
133                         break;
134
135                 case OPS:
136                         userId = user.getUserId();
137                         response = handleOps(userId);
138                         break;
139
140                 case PRODUCT_STRATEGIST:
141                         userId = user.getUserId();
142                         response = handleProductStrategist(userId);
143                         break;
144
145                 case PRODUCT_MANAGER:
146                         userId = user.getUserId();
147                         response = handleProductManager(userId);
148                         break;
149
150                 case ADMIN:
151                         response = handleAdmin();
152                         break;
153
154                 default:
155                         response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
156                         break;
157                 }
158                 return response;
159
160         }
161
162         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleAdmin() {
163                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
164                 // userId should stay null
165                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
166                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
167                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
168                 response = getFollowedResourcesAndServices(null, lifecycleStates, lastStateStates);
169                 return response;
170         }
171
172         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
173                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
174                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
175                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
176                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
177                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
178                 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
179                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
180                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
181                 // more states
182                 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
183                 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
184                 return response;
185         }
186
187         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleGovernor(String userId) {
188                 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(null);
189                 return result;
190         }
191
192         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductStrategist(String userId) {
193                 // Should be empty list according to Ella, 13/03/16
194                 Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
195                 result.put("products", new ArrayList<>());
196                 return Either.left(result);
197         }
198
199         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
200                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
201                 Set<LifecycleStateEnum> lastStateStates = new HashSet<LifecycleStateEnum>();
202                 Either<Map<String, List<? extends Component>>, ResponseFormat> response;
203                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
204                 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
205                 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
206                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
207                 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
208                 // more states
209                 lastStateStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
210                 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
211                 return response;
212         }
213
214         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleOps(String userId) {
215                 Set<DistributionStatusEnum> distStatus = new HashSet<DistributionStatusEnum>();
216                 distStatus.add(DistributionStatusEnum.DISTRIBUTION_APPROVED);
217                 distStatus.add(DistributionStatusEnum.DISTRIBUTED);
218
219                 Either<Map<String, List<? extends Component>>, ResponseFormat> result = handleFollowedCertifiedServices(distStatus);
220                 return result;
221         }
222
223         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleFollowedCertifiedServices(Set<DistributionStatusEnum> distStatus) {
224
225                 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getCertifiedServicesWithDistStatus(distStatus);
226                 if (services.isLeft()) {
227                         Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
228                         List<Service> list = new ArrayList<>();
229                         list.addAll(services.left().value());
230                         result.put("services", list);
231                         return Either.left(result);
232                 } else {
233                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
234                 }
235         }
236
237         private Either<Map<String, List<? extends Component>>, ResponseFormat> handleTester(String userId) {
238                 Set<LifecycleStateEnum> lifecycleStates = new HashSet<LifecycleStateEnum>();
239                 lifecycleStates.add(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
240                 lifecycleStates.add(LifecycleStateEnum.READY_FOR_CERTIFICATION);
241                 Either<Map<String, List<? extends Component>>, ResponseFormat> result = getFollowedResourcesAndServices(null, lifecycleStates, null);
242
243                 return result;
244         }
245
246         private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
247
248                 try {
249                         Either<List<Resource>, StorageOperationStatus> resources = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
250
251                         if (resources.isLeft()) {
252                                 Either<List<Service>, StorageOperationStatus> services = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
253                                 if (services.isLeft()) {
254                                         Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
255                                         result.put("services", services.left().value());
256                                         result.put("resources", resources.left().value());
257                                         return Either.left(result);
258                                 } else {
259                                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
260                                 }
261                         } else {
262                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
263                         }
264                 } finally {
265                         titanDao.commit();
266                 }
267         }
268
269         private Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates, Set<LifecycleStateEnum> lastStateStates) {
270                 Either<List<Product>, StorageOperationStatus> products = toscaOperationFacade.getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
271                 if (products.isLeft()) {
272                         Map<String, List<? extends Component>> result = new HashMap<String, List<? extends Component>>();
273                         result.put("products", products.left().value());
274                         return Either.left(result);
275                 } else {
276                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
277                 }
278         }
279
280         /*
281          * New categories flow - start
282          */
283         public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
284                 return elementOperation.getAllResourceCategories();
285         }
286
287         public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
288                 return elementOperation.getAllServiceCategories();
289         }
290
291         public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
292
293                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
294                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
295                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
296                 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
297
298                 User user = new User();
299                 Either<User, ResponseFormat> validateUser = validateUser(userId);
300                 if (validateUser.isRight()) {
301                         log.debug("Validation of user failed, userId {}", userId);
302                         ResponseFormat responseFormat = validateUser.right().value();
303                         user = new User();
304                         user.setUserId(userId);
305                         String currCategoryName = (category == null ? null : category.getName());
306                         handleCategoryAuditing(responseFormat, user, currCategoryName, auditingAction, componentType);
307                         return Either.right(responseFormat);
308                 }
309
310                 user = validateUser.left().value();
311
312                 if (category == null) {
313                         log.debug("Category json is invalid");
314                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
315                         handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
316                         return Either.right(responseFormat);
317                 }
318
319                 String categoryName = category.getName();
320                 // For auditing of failures we need the original non-normalized name
321                 String origCategoryName = categoryName;
322                 if (componentTypeEnum == null) {
323                         log.debug("Component type {} is invalid", componentTypeParamName);
324                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
325                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
326                         return Either.right(responseFormat);
327                 }
328
329                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
330                 if (validateUserRole.isRight()) {
331                         log.debug("Validation of user role failed, userId {}", userId);
332                         ResponseFormat responseFormat = validateUserRole.right().value();
333                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
334                         return Either.right(responseFormat);
335                 }
336
337                 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
338                         log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
339                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
340                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
341                         return Either.right(responseFormat);
342                 }
343
344                 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
345
346                 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
347                         log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName, componentType);
348                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
349                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
350                         return Either.right(responseFormat);
351                 }
352
353                 category.setName(categoryName);
354
355                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
356                 category.setNormalizedName(normalizedName);
357
358                 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
359
360                 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
361                 if (categoryUniqueEither.isRight()) {
362                         log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
363                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
364                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
365                         return Either.right(responseFormat);
366                 }
367
368                 Boolean isCategoryUnique = categoryUniqueEither.left().value();
369                 if (!isCategoryUnique) {
370                         log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
371                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
372                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
373                         return Either.right(responseFormat);
374                 }
375
376                 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
377                 if (createCategoryByType.isRight()) {
378                         log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
379                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
380                         handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
381                         return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
382                 }
383                 category = createCategoryByType.left().value();
384                 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
385                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
386                 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
387                 return Either.left(category);
388         }
389
390         public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName, String parentCategoryId, String userId) {
391
392                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
393                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
394                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
395                 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
396                 // For auditing
397                 String parentCategoryName = parentCategoryId;
398
399                 if (subCategory == null) {
400                         log.debug("Sub-category json is invalid");
401                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
402                         handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
403                         return Either.right(responseFormat);
404                 }
405
406                 String subCategoryName = subCategory.getName();
407                 // For auditing of failures we need the original non-normalized name
408                 String origSubCategoryName = subCategoryName;
409
410                 User user = new User();
411                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "createSubCategory", false);
412                 if (validateUser.isRight()) {
413                         log.debug("Validation of user failed, userId {}", userId);
414                         ResponseFormat responseFormat = validateUser.right().value();
415                         user = new User();
416                         user.setUserId(userId);
417                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
418                         return Either.right(responseFormat);
419                 }
420
421                 user = validateUser.left().value();
422
423                 if (componentTypeEnum == null) {
424                         log.debug("Component type {} is invalid", componentTypeParamName);
425                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
426                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
427                         return Either.right(responseFormat);
428                 }
429
430                 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
431                 if (validateComponentType.isRight()) {
432                         log.debug("Validation of component type for sub-category failed");
433                         ResponseFormat responseFormat = validateComponentType.right().value();
434                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
435                         return Either.right(responseFormat);
436                 }
437
438                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
439                 if (validateUserRole.isRight()) {
440                         log.debug("Validation of user role failed, userId {}", userId);
441                         ResponseFormat responseFormat = validateUserRole.right().value();
442                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
443                         return Either.right(responseFormat);
444                 }
445
446                 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
447                 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
448
449                 CategoryDefinition categoryDefinition;
450                 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId, componentTypeEnum);
451                 if (validateCategoryExists.isRight()) {
452                         log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
453                         ResponseFormat responseFormat = validateCategoryExists.right().value();
454                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
455                         return Either.right(responseFormat);
456                 }
457
458                 categoryDefinition = validateCategoryExists.left().value();
459                 parentCategoryName = categoryDefinition.getName();
460
461                 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
462                         log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
463                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
464                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
465                         return Either.right(responseFormat);
466                 }
467
468                 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
469
470                 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
471                         log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName, componentType);
472                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
473                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
474                         return Either.right(responseFormat);
475                 }
476
477                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
478                 subCategory.setNormalizedName(normalizedName);
479
480                 // Uniqueness under this category
481                 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation.isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
482                 if (subCategoryUniqueForCategory.isRight()) {
483                         log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
484                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
485                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
486                         return Either.right(responseFormat);
487                 }
488
489                 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
490                 if (!isSubUnique) {
491                         log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName, normalizedName, componentType);
492                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
493                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
494                         return Either.right(responseFormat);
495                 }
496
497                 // Setting name of subcategory to fit the similar subcategory name
498                 // ignoring cases.
499                 // For example if Network-->kUKU exists for service category Network,
500                 // and user is trying to create Router-->Kuku for service category
501                 // Router,
502                 // his subcategory name will be Router-->kUKU.
503                 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation.getSubCategoryUniqueForType(childNodeType, normalizedName);
504                 if (subCategoryUniqueForType.isRight()) {
505                         log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
506                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
507                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
508                         return Either.right(responseFormat);
509                 }
510                 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
511                 if (subCategoryDefinition != null) {
512                         subCategoryName = subCategoryDefinition.getName();
513                 }
514
515                 subCategory.setName(subCategoryName);
516                 ///////////////////////////////////////////// Validations end
517
518                 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation.createSubCategory(parentCategoryId, subCategory, childNodeType);
519                 if (createSubCategory.isRight()) {
520                         log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
521                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
522                         handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
523                         return Either.right(responseFormat);
524                 }
525
526                 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
527                 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
528                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
529                 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
530                 return Either.left(subCategoryCreated);
531         }
532
533         public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName, String grandParentCategoryId, String parentSubCategoryId, String userId) {
534
535                 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
536                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
537                 String componentType = (componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue());
538                 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
539                 // For auditing
540                 String parentCategoryName = grandParentCategoryId;
541                 String parentSubCategoryName = parentSubCategoryId;
542
543                 User user;
544                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "create Grouping", false);
545                 if (validateUser.isRight()) {
546                         log.debug("Validation of user failed, userId {}", userId);
547                         ResponseFormat responseFormat = validateUser.right().value();
548                         user = new User();
549                         user.setUserId(userId);
550                         String groupingNameForAudit = (grouping == null ? null : grouping.getName());
551                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
552                         return Either.right(responseFormat);
553                 }
554
555                 user = validateUser.left().value();
556
557                 if (grouping == null) {
558                         log.debug("Grouping json is invalid");
559                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
560                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
561                         return Either.right(responseFormat);
562                 }
563
564                 String groupingName = grouping.getName();
565                 // For auditing of failures we need the original non-normalized name
566                 String origGroupingName = groupingName;
567
568                 if (componentTypeEnum == null) {
569                         log.debug("Component type {} is invalid", componentTypeParamName);
570                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
571                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
572                         return Either.right(responseFormat);
573                 }
574
575                 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
576                 if (validateComponentType.isRight()) {
577                         log.debug("Validation of component type for grouping failed");
578                         ResponseFormat responseFormat = validateComponentType.right().value();
579                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
580                         return Either.right(responseFormat);
581                 }
582
583                 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
584                 if (validateUserRole.isRight()) {
585                         log.debug("Validation of user role failed, userId {}", userId);
586                         ResponseFormat responseFormat = validateUserRole.right().value();
587                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
588                         return Either.right(responseFormat);
589                 }
590
591                 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
592                 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
593                 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
594
595                 // Validate category
596                 CategoryDefinition categoryDefinition;
597                 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId, componentTypeEnum);
598                 if (validateCategoryExists.isRight()) {
599                         log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
600                         ResponseFormat responseFormat = validateCategoryExists.right().value();
601                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
602                         return Either.right(responseFormat);
603                 }
604
605                 categoryDefinition = validateCategoryExists.left().value();
606                 parentCategoryName = categoryDefinition.getName();
607
608                 // Validate subcategory
609                 SubCategoryDefinition subCategoryDefinition;
610                 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId, componentTypeEnum);
611                 if (validateSubCategoryExists.isRight()) {
612                         log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
613                         ResponseFormat responseFormat = validateSubCategoryExists.right().value();
614                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
615                         return Either.right(responseFormat);
616                 }
617
618                 subCategoryDefinition = validateSubCategoryExists.left().value();
619                 parentSubCategoryName = subCategoryDefinition.getName();
620
621                 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
622                         log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
623                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
624                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
625                         return Either.right(responseFormat);
626                 }
627
628                 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
629
630                 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
631                         log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName, componentType);
632                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
633                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
634                         return Either.right(responseFormat);
635                 }
636
637                 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
638                 grouping.setNormalizedName(normalizedName);
639
640                 // Uniqueness under this category
641                 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation.isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
642                 if (groupingUniqueForSubCategory.isRight()) {
643                         log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
644                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
645                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
646                         return Either.right(responseFormat);
647                 }
648
649                 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
650                 if (!isGroupingUnique) {
651                         log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName, normalizedName, componentType);
652                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
653                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
654                         return Either.right(responseFormat);
655                 }
656
657                 // Setting name of grouping to fit the similar grouping name ignoring
658                 // cases.
659                 // For example if Network-->kUKU exists for service sub-category
660                 // Network, and user is trying to create grouping Router-->Kuku for
661                 // service sub-category Router,
662                 // his grouping name will be Router-->kUKU.
663                 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
664                 if (groupingUniqueForType.isRight()) {
665                         log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
666                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
667                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
668                         return Either.right(responseFormat);
669                 }
670                 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
671                 if (groupingDefinition != null) {
672                         groupingName = groupingDefinition.getName();
673                 }
674
675                 grouping.setName(groupingName);
676                 ///////////////////////////////////////////// Validations end
677
678                 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
679                 if (createGrouping.isRight()) {
680                         log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
681                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
682                         handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
683                         return Either.right(responseFormat);
684                 }
685
686                 GroupingDefinition groupingCreated = createGrouping.left().value();
687                 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
688                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
689                 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction, componentType);
690                 return Either.left(groupingCreated);
691         }
692
693         public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
694                 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
695                 ResponseFormat responseFormat;
696                 User user = new User();
697                 if (userId == null) {
698                         user.setUserId("UNKNOWN");
699                         responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
700                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
701                         return Either.right(responseFormat);
702                 }
703
704                 Either<User, ResponseFormat> validateUser = validateUserExists(userId, "get All Categories", false);
705                 if (validateUser.isRight()) {
706                         user.setUserId(userId);
707                         log.debug("Validation of user failed, userId {}", userId);
708                         responseFormat = validateUser.right().value();
709                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
710                         return Either.right(responseFormat);
711                 }
712                 user = validateUser.left().value();
713
714                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
715                 if (componentTypeEnum == null) {
716                         log.debug("Cannot create category for component type {}", componentType);
717                         responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
718                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
719                         return Either.right(responseFormat);
720                 }
721
722                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
723                 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
724                 if (getAllCategoriesByType.isRight()) {
725                         responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
726                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
727                         return Either.right(responseFormat);
728                 }
729                 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
730                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
731                 componentsUtils.auditGetCategoryHierarchy(auditingAction, user, componentType, responseFormat);
732                 return Either.left(categories);
733         }
734         
735         public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
736                 AuditingActionEnum auditingAction = AuditingActionEnum.GET_CATEGORY_HIERARCHY;
737                 ResponseFormat responseFormat;
738                 UiCategories categories = new UiCategories();
739                 
740                 Either<User, ResponseFormat> userResponse = validateUserExists(userId, "get all categories", false);
741
742                 if (userResponse.isRight()) {
743                         return Either.right(userResponse.right().value());
744                 }
745                 User user = userResponse.left().value();
746                 
747                 //GET resource categories
748                 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
749                 if (getResourceCategoriesByType.isRight()) {
750                         responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
751                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
752                         return Either.right(responseFormat);
753                 }
754                 categories.setResourceCategories(getResourceCategoriesByType.left().value());
755                 
756                 //GET service categories
757                 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
758                 if (getServiceCategoriesByType.isRight()) {
759                         responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
760                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
761                         return Either.right(responseFormat);
762                 }
763                 categories.setServiceCategories(getServiceCategoriesByType.left().value());
764                 
765                 //GET product categories
766                 Either<List<CategoryDefinition>, ActionStatus> getProductCategoriesByType = elementOperation.getAllCategories(NodeTypeEnum.ProductCategory, false);
767                 if (getProductCategoriesByType.isRight()) {
768                         responseFormat = componentsUtils.getResponseFormat(getProductCategoriesByType.right().value());
769                         componentsUtils.auditGetCategoryHierarchy(auditingAction, user, ComponentTypeEnum.PRODUCT.getValue(), responseFormat);
770                         return Either.right(responseFormat);
771                 }
772                 
773                 categories.setProductCategories(getProductCategoriesByType.left().value());
774                 return Either.left(categories);
775                 
776         }
777
778         public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
779
780                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Category", false);
781                 if (resp.isRight()) {
782                         return Either.right(resp.right().value());
783                 }
784
785                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
786                 if (componentTypeEnum == null) {
787                         log.debug("Cannot create category for component type {}", componentTypeParamName);
788                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
789                 }
790
791                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
792
793                 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
794                 if (deleteCategoryByType.isRight()) {
795                         // auditing, logging here...
796                         return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
797                 }
798                 CategoryDefinition category = deleteCategoryByType.left().value();
799                 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
800                 return Either.left(category);
801         }
802
803         public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String grandParentCategoryId, String parentSubCategoryId, String componentTypeParamName, String userId) {
804
805                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Sub Category", false);
806                 if (resp.isRight()) {
807                         return Either.right(resp.right().value());
808                 }
809
810                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
811                 if (componentTypeEnum == null) {
812                         log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
813                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
814                 }
815
816                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
817
818                 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
819                 if (deleteSubCategoryByType.isRight()) {
820                         // auditing, logging here...
821                         return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
822                 }
823                 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
824                 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
825                 return Either.left(subCategory);
826         }
827
828         public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String grandParentCategoryId, String parentSubCategoryId, String groupingId, String componentTypeParamName, String userId) {
829
830                 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Grouping", false);
831                 if (resp.isRight()) {
832                         return Either.right(resp.right().value());
833                 }
834
835                 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
836                 if (componentTypeEnum == null) {
837                         log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
838                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
839                 }
840
841                 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
842
843                 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
844                 if (deleteGroupingByType.isRight()) {
845                         // auditing, logging here...
846                         return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
847                 }
848                 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
849                 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
850                 return Either.left(deletedGrouping);
851         }
852
853         private Either<User, ResponseFormat> validateUser(String userId) {
854
855                 // validate user exists
856                 if (userId == null) {
857                         log.debug("UserId is null");
858                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION));
859                 }
860
861                 Either<User, ActionStatus> userResult = userAdminManager.getUser(userId, false);
862                 if (userResult.isRight()) {
863                         ResponseFormat responseFormat;
864                         if (userResult.right().value().equals(ActionStatus.USER_NOT_FOUND)) {
865                                 log.debug("Not authorized user, userId = {}", userId);
866                                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
867                         } else {
868                                 log.debug("Failed to authorize user, userId = {}", userId);
869                                 responseFormat = componentsUtils.getResponseFormat(userResult.right().value());
870                         }
871
872                         return Either.right(responseFormat);
873                 }
874                 return Either.left(userResult.left().value());
875                 // ========================================-
876         }
877
878         private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
879                 String role = user.getRole();
880                 boolean validAdminAction = (role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE));
881                 boolean validProductAction = (role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT));
882
883                 if (!(validAdminAction || validProductAction)) {
884                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
885                         log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role, componentTypeEnum);
886                         return Either.right(responseFormat);
887                 }
888                 return Either.left(true);
889         }
890
891         private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
892                 boolean validResourceAction = (componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY || categoryType == CategoryTypeEnum.SUBCATEGORY));
893                 boolean validServiceAction = (componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY);
894                 boolean validProductAction = (componentType == ComponentTypeEnum.PRODUCT); // can
895                                                                                                                                                                         // be
896                                                                                                                                                                         // any
897                                                                                                                                                                         // category
898                                                                                                                                                                         // type
899
900                 if (!(validResourceAction || validServiceAction || validProductAction)) {
901                         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
902                         log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
903                         return Either.right(responseFormat);
904                 }
905                 return Either.left(true);
906         }
907
908         private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId, ComponentTypeEnum componentType) {
909                 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
910                 if (categoryByTypeAndId.isRight()) {
911                         log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
912                         ActionStatus actionStatus = categoryByTypeAndId.right().value();
913                         ResponseFormat responseFormat;
914                         if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
915                                 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
916                         } else {
917                                 responseFormat = componentsUtils.getResponseFormat(actionStatus);
918                         }
919                         return Either.right(responseFormat);
920                 }
921                 return Either.left(categoryByTypeAndId.left().value());
922         }
923
924         private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId, ComponentTypeEnum componentType) {
925                 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
926                 if (subCategoryByTypeAndId.isRight()) {
927                         log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
928                         ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
929                         ResponseFormat responseFormat;
930                         if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
931                                 responseFormat = componentsUtils.getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
932                         } else {
933                                 responseFormat = componentsUtils.getResponseFormat(actionStatus);
934                         }
935                         return Either.right(responseFormat);
936                 }
937                 return Either.left(subCategoryByTypeAndId.left().value());
938         }
939
940         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction, String componentType) {
941                 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
942         }
943
944         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, AuditingActionEnum auditingAction, String componentType) {
945                 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
946         }
947
948         private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping, AuditingActionEnum auditingAction, String componentType) {
949                 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
950         }
951
952         /*
953          * New categories flow - end
954          */
955
956         public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
957                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Tags");
958                 if (resp.isRight()) {
959                         return Either.right(resp.right().value());
960                 }
961                 return elementOperation.getAllTags();
962         }
963
964         public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
965                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Property Scopes");
966                 if (resp.isRight()) {
967                         return Either.right(resp.right().value());
968                 }
969                 return elementOperation.getAllPropertyScopes();
970         }
971
972         public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(String userId) {
973                 Either<User, ActionStatus> resp = validateUserExistsActionStatus(userId, "get All Artifact Types");
974                 if (resp.isRight()) {
975                         return Either.right(resp.right().value());
976                 }
977                 return elementOperation.getAllArtifactTypes();
978         }
979
980         public Either<Map<String, Object>, ActionStatus> getAllDeploymentArtifactTypes() {
981                 return elementOperation.getAllDeploymentArtifactTypes();
982         }
983
984         public Either<Integer, ActionStatus> getDefaultHeatTimeout() {
985                 return elementOperation.getDefaultHeatTimeout();
986         }
987
988         public Either<Map<String, List<? extends Component>>, ResponseFormat> getCatalogComponents(String userId) {
989                 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Catalog Components", false);
990                 if (resp.isRight()) {
991                         return Either.right(resp.right().value());
992                 }
993                 Map<String, List<? extends Component>> resMap = new HashMap<>();
994
995                 Either<List<Resource>, StorageOperationStatus> resResources = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.RESOURCE, true);
996                 if (resResources.isLeft()) {
997                         Either<List<Service>, StorageOperationStatus> resServices = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.SERVICE, true);
998                         if (resServices.isLeft()) {
999                                 // Either<List<Product>, StorageOperationStatus> resProducts = productOperation.getProductCatalogData(false);
1000                                 // if (resProducts.isLeft()) {
1001                                 resMap.put("resources", resResources.left().value());
1002                                 resMap.put("services", resServices.left().value());
1003                                 resMap.put("products", new ArrayList<>());
1004                                 
1005                                 return Either.left(resMap);
1006                         } else {
1007                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resServices.right().value())));
1008                         }
1009                 } else {
1010                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resResources.right().value())));
1011                 }
1012         }
1013
1014         public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, String> filters, String query) {
1015                 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1016
1017                 if (query != null) {
1018                         Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
1019                         if (invalidFilter.isPresent()) {
1020                                 log.debug("getFilteredAssetList: invalid filter key");
1021                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(), FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
1022                         }
1023                 }
1024
1025                 if (filters == null || filters.isEmpty()) {
1026                         Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, false);
1027                         if(componentsList.isRight()) {
1028                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
1029                         }
1030                         return Either.left(componentsList.left().value());
1031                 }
1032
1033                 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
1034
1035                 if (result.isRight()) {// category hierarchy mismatch or
1036                                                                 // category/subCategory/distributionStatus not
1037                                                                 // found
1038                         List<String> params = getErrorResponseParams(filters, assetTypeEnum);
1039                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
1040                 }
1041                 if (result.left().value().isEmpty()) {// no assets found for requested
1042                                                                                                 // criteria
1043                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
1044                 }
1045                 return Either.left(result.left().value());
1046         }
1047
1048         private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType, boolean inTransaction) {
1049                 Either<List<Component>, StorageOperationStatus> assetResult = null;
1050                 if(assetType == ComponentTypeEnum.RESOURCE){
1051                          
1052                         assetResult = getFilteredResouces(filters, inTransaction);
1053                         
1054                 } else if (assetType == ComponentTypeEnum.SERVICE){
1055                         
1056                         assetResult = getFilteredServices(filters, inTransaction);
1057                 }
1058                 return assetResult;
1059         }
1060
1061         private <T> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1062                 
1063                 Either<List<T>, StorageOperationStatus> components = null;
1064
1065                 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1066                 String distributionStatus = filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
1067                 DistributionStatusEnum distEnum = DistributionStatusEnum.findState(distributionStatus);
1068                 if (distributionStatus != null && distEnum == null) {
1069                         filters.remove(FilterKeyEnum.CATEGORY);
1070                         return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1071                 }
1072
1073                 if (categoryName != null) { // primary filter
1074                         components = fetchByCategoryOrSubCategoryName(categoryName, NodeTypeEnum.ServiceNewCategory, GraphEdgeLabels.CATEGORY.getProperty(), NodeTypeEnum.Service, inTransaction, ServiceMetadataData.class, null);
1075                         if (components.isLeft() && distEnum != null) {// secondary filter
1076                                 Predicate<T> statusFilter = p -> ((Service) p).getDistributionStatus().equals(distEnum);
1077                                 return Either.left(components.left().value().stream().filter(statusFilter).collect(Collectors.toList()));
1078                         }
1079                         filters.remove(FilterKeyEnum.DISTRIBUTION_STATUS);
1080                         return components;
1081                 }
1082
1083                 Set<DistributionStatusEnum> distStatusSet = new HashSet<>();
1084                 distStatusSet.add(distEnum);
1085                 Either<List<Service>, StorageOperationStatus> servicesWithDistStatus = toscaOperationFacade.getServicesWithDistStatus(distStatusSet, null);
1086                 if (servicesWithDistStatus.isRight()) { // not found == empty list
1087                         return Either.left(new ArrayList<>());
1088                 }
1089                 
1090                 return Either.left((List<T>)servicesWithDistStatus.left().value());
1091         }
1092
1093         public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1094
1095                 if (assetType == null || assetType == null) {
1096                         log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1097                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1098                 }
1099
1100                 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1101
1102                 if (assetTypeEnum == null) {
1103                         log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1104                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1105                 }
1106                 
1107                 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1108                 
1109                 switch (assetTypeEnum) {
1110                 case RESOURCE:
1111                         additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1112                         break;
1113                 case SERVICE:
1114                         additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1115                         break;
1116                 default:
1117                         log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1118                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1119                 }
1120                 
1121                 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch);
1122                 if(componentsListByUuid.isRight()) {
1123                         log.debug("getCatalogComponentsByUuidAndAssetType: Service fetching failed");
1124                         ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), ComponentTypeEnum.SERVICE);
1125                         return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1126                 }
1127                 
1128                 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + "Service fetching successful");
1129                 return Either.left(componentsListByUuid.left().value());
1130         }
1131
1132         public List<String> getAllComponentTypesParamNames() {
1133                 List<String> paramNames = new ArrayList<>();
1134                 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1135                 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1136                 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1137                 return paramNames;
1138         }
1139
1140         public List<String> getAllSupportedRoles() {
1141                 Role[] values = Role.values();
1142                 List<String> roleNames = new ArrayList<>();
1143                 for (Role role : values) {
1144                         roleNames.add(role.name());
1145                 }
1146                 return roleNames;
1147         }
1148
1149         public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1150                 return elementOperation.getResourceTypesMap();
1151         }
1152
1153         private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1154                 List<NameValuePair> params = URLEncodedUtils.parse(query, StandardCharsets.UTF_8);
1155                 List<String> validKeys = FilterKeyEnum.getValidFiltersByAssetType(assetType);
1156                 Predicate<NameValuePair> noMatch = p -> !validKeys.contains(p.getName());
1157                 return params.stream().filter(noMatch).findAny();
1158         }
1159
1160         private List<String> getErrorResponseParams(Map<FilterKeyEnum, String> filters, ComponentTypeEnum assetType) {
1161                 List<String> params = new ArrayList<String>();
1162                 if (1 == filters.size()) {
1163                         params.add(assetType.getValue().toLowerCase());
1164                         params.add(filters.keySet().iterator().next().getName());
1165                         params.add(filters.values().iterator().next());
1166                 } else {
1167                         params.add(assetType.getValue());
1168                         params.add(filters.get(FilterKeyEnum.SUB_CATEGORY));
1169                         params.add(filters.get(FilterKeyEnum.CATEGORY));
1170                 }
1171                 return params;
1172         }
1173         
1174         public Either<List<Component>, StorageOperationStatus> getFilteredResouces(Map<FilterKeyEnum, String> filters, boolean inTransaction) {
1175
1176                 String subCategoryName = filters.get(FilterKeyEnum.SUB_CATEGORY);
1177                 String categoryName = filters.get(FilterKeyEnum.CATEGORY);
1178                 ResourceTypeEnum resourceType = ResourceTypeEnum.getType( filters.get(FilterKeyEnum.RESOURCE_TYPE));
1179                 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1180                 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1181
1182                 if (categoryName != null) {
1183                         subcategories = getAllSubCategories(categoryName);
1184                         if (subcategories.isRight()) {
1185                                 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1186                                 return Either.right(subcategories.right().value());
1187                         }
1188                 }
1189                 if (subCategoryName != null) { // primary filter
1190                         if (categoryName != null) {
1191                                 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1192                                 if (!subCategoryData.isPresent()) {
1193                                         return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1194                                 }
1195                                 return fetchByCategoryOrSubCategoryUid((String) subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction,
1196                                                 ResourceMetadataData.class, resourceType);
1197                         }
1198
1199                         return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource, inTransaction, ResourceMetadataData.class, resourceType);
1200                 }
1201                 if(subcategories != null){
1202                         return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1203                 }
1204                 return fetchByResourceType(filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1205         }
1206         
1207         private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1208                 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation.getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1209                 if (categoryResult.isRight()) {
1210                         return Either.right(categoryResult.right().value());
1211                 }
1212                 CategoryData categoryData = categoryResult.left().value();
1213
1214                 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), (String) categoryData.getUniqueId(),
1215                                 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1216                 if (childrenNodes.isRight()) {
1217                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
1218                 }
1219                 return Either.left(childrenNodes.left().value());
1220         }
1221         
1222         private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes, String subCategoryName) {
1223                 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName().equals(subCategoryName);
1224                 return childNodes.stream().filter(matchName).findAny();
1225         }
1226         
1227         protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1228                         Class<S> clazz, ResourceTypeEnum resourceType) {
1229                 try {
1230                         Either<TitanGraph, TitanOperationStatus> graph = titanDao.getGraph();
1231                         if (graph.isRight()) {
1232                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(graph.right().value()));
1233
1234                         }
1235                         return collectComponents(graph.left().value(), neededType, categoryUid, categoryType, clazz, resourceType);
1236
1237                 } finally {
1238                         if (false == inTransaction) {
1239                                 titanDao.commit();
1240                         }
1241                 }
1242         }
1243         
1244         protected <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName, NodeTypeEnum categoryType, String categoryLabel, NodeTypeEnum neededType, boolean inTransaction,
1245                         Class<S> clazz, ResourceTypeEnum resourceType) {
1246                 List<T> components = new ArrayList<>();
1247                 try {
1248                         Class categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1249                         Map<String, Object> props = new HashMap<String, Object>();
1250                         props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1251                         Either<List<GraphNode>, TitanOperationStatus> getCategory = titanGenericDao.getByCriteria(categoryType, props, categoryClazz);
1252                         if (getCategory.isRight()) {
1253                                 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1254                         }
1255                         Either<TitanGraph, TitanOperationStatus> graph = titanDao.getGraph();
1256                         if (graph.isRight()) {
1257                                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(graph.right().value()));
1258
1259                         }
1260                         for (GraphNode category : getCategory.left().value()) {
1261                                 Either<List<T>, StorageOperationStatus> result = collectComponents(graph.left().value(), neededType, (String) category.getUniqueId(), categoryType, clazz, resourceType);
1262                                 if (result.isRight()) {
1263                                         return result;
1264                                 }
1265                                 components.addAll(result.left().value());
1266                         }
1267
1268                         return Either.left(components);
1269                 } finally {
1270                         if (false == inTransaction) {
1271                                 titanDao.commit();
1272                         }
1273                 }
1274         }
1275         
1276         private <T, S extends ComponentMetadataData> Either<List<T>, StorageOperationStatus> collectComponents(TitanGraph graph, NodeTypeEnum neededType, String categoryUid, NodeTypeEnum categoryType, Class<S> clazz, ResourceTypeEnum resourceType) {
1277                 List<T> components = new ArrayList<>();
1278                 Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> parentNodes = titanGenericDao.getParentNodes(UniqueIdBuilder.getKeyByNodeType(categoryType), categoryUid, GraphEdgeLabels.CATEGORY, neededType, clazz);
1279                 if (parentNodes.isLeft()) {
1280                         for (ImmutablePair<S, GraphEdge> component : parentNodes.left().value()) {
1281                                 ComponentMetadataDataDefinition componentData = component.getLeft().getMetadataDataDefinition();
1282                                 Boolean isHighest = componentData.isHighestVersion();
1283                                 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, componentData);
1284                                 
1285                                 if (isHighest && isMatchingResourceType) {
1286                                         Either<T, StorageOperationStatus> result = (Either<T, StorageOperationStatus>) toscaOperationFacade.getToscaElement(componentData.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1287                                         if (result.isRight()) {
1288                                                 return Either.right(result.right().value());
1289                                         }
1290                                         components.add(result.left().value());
1291                                 }
1292                         }
1293                 }
1294                 return Either.left(components);
1295         }
1296         
1297         private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType,
1298                         ComponentMetadataDataDefinition componentData) {
1299
1300                 boolean isMatching;
1301                 if (componentType == NodeTypeEnum.Resource) {
1302                         if (resourceType == null) {
1303                                 isMatching = true;
1304                         } else {
1305                                 isMatching = resourceType == ((ResourceMetadataDataDefinition)componentData).getResourceType();
1306                         }
1307                 } else {
1308                         isMatching = true;
1309                 }
1310                 return isMatching;
1311         }
1312         
1313         private <T> Either<List<T>, StorageOperationStatus> fetchByMainCategory(List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1314                 List<T> components = new ArrayList<>();
1315
1316                 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1317                         Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid((String) subCategory.getLeft().getUniqueId(), NodeTypeEnum.ResourceSubcategory, GraphEdgeLabels.SUB_CATEGORY.getProperty(), NodeTypeEnum.Resource,
1318                                         inTransaction, ResourceMetadataData.class, resourceType);
1319                         if (fetched.isRight()) {
1320                                 // return fetched;
1321                                 continue;
1322                         }
1323                         components.addAll(fetched.left().value());
1324                 }
1325                 return Either.left(components);
1326         }
1327         
1328         private  Either<List<Component>, StorageOperationStatus> fetchByResourceType(String resourceType, boolean inTransaction) {
1329                 List<Component> components = null;
1330                 StorageOperationStatus status;
1331                 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1332                 Either<List<Component>, StorageOperationStatus> result;
1333                 try {
1334
1335                         Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade.fetchByResourceType(resourceType); //titanGenericDao.getByCriteria(nodeType, props, clazz);
1336                         if (getResources.isRight()) {
1337                                 status = getResources.right().value();
1338                                 if(status != StorageOperationStatus.NOT_FOUND){
1339                                         statusWrapper.setInnerElement(getResources.right().value());
1340                                 }else{
1341                                         components = new ArrayList<>();
1342                                 }
1343                         } else{
1344                                 components = getResources.left().value();
1345                         }
1346                         if(!statusWrapper.isEmpty()){
1347                                 result = Either.right(statusWrapper.getInnerElement());
1348                         }else{
1349                                 result = Either.left(components);
1350                         }
1351                         return result;
1352                 } finally {
1353                         if (!inTransaction) {
1354                                 titanDao.commit();
1355                         }
1356                 }
1357         }
1358         
1359         Component convertComponentMetadataDataToComponent(ComponentMetadataData componentMetadataData) {
1360                 return convertResourceDataToResource((ResourceMetadataData) componentMetadataData);
1361         }
1362         private Resource convertResourceDataToResource(ResourceMetadataData resourceData) {
1363
1364                 ResourceMetadataDefinition resourceMetadataDataDefinition = new ResourceMetadataDefinition((ResourceMetadataDataDefinition) resourceData.getMetadataDataDefinition());
1365
1366                 Resource resource = new Resource(resourceMetadataDataDefinition);
1367
1368                 return resource;
1369         }
1370         private <T> Either<List<T>, StorageOperationStatus> fetchByDistributionStatus(String status, boolean inTransaction) {
1371                 Map<String, Object> props = new HashMap<String, Object>();
1372                 props.put(GraphPropertiesDictionary.DISTRIBUTION_STATUS.getProperty(), status);
1373                 props.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true);
1374                 return (Either<List<T>, StorageOperationStatus>) (Either<?, StorageOperationStatus>) getServiceListByCriteria(props, inTransaction);
1375         }
1376         
1377         private Either<List<Service>, StorageOperationStatus> getServiceListByCriteria(Map<String, Object> props, boolean inTransaction) {
1378                 props.put(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.Service.getName());
1379                 Either<List<ServiceMetadataData>, TitanOperationStatus> byCriteria = titanGenericDao.getByCriteria(NodeTypeEnum.Service, props, ServiceMetadataData.class);
1380
1381                 if (byCriteria.isRight()) {
1382                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value()));
1383                 }
1384                 List<Service> services = new ArrayList<Service>();
1385                 List<ServiceMetadataData> servicesDataList = byCriteria.left().value();
1386                 for (ServiceMetadataData data : servicesDataList) {
1387                         Either<Component, StorageOperationStatus> service = toscaOperationFacade.getToscaElement(data.getMetadataDataDefinition().getUniqueId());
1388                         if (service.isLeft()) {
1389                                 services.add((Service)service.left().value());
1390                         } else {
1391                                 log.debug("Failed to fetch resource for name = {}  and id = {}",data.getMetadataDataDefinition().getName(),data.getUniqueId());
1392                         }
1393                 }
1394                 return Either.left(services);
1395         }
1396
1397 }