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