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