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