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