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