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