2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
22 package org.openecomp.sdc.be.components.impl;
24 import static org.apache.commons.lang.BooleanUtils.isTrue;
25 import static org.openecomp.sdc.be.components.impl.ImportUtils.Constants.DEFAULT_ICON;
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;
37 import java.util.Objects;
38 import java.util.Optional;
40 import java.util.function.Predicate;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
43 import java.util.stream.Collectors;
44 import org.apache.commons.collections4.CollectionUtils;
45 import org.apache.commons.collections4.MapUtils;
46 import org.apache.commons.lang3.StringUtils;
47 import org.apache.commons.lang3.tuple.ImmutablePair;
48 import org.apache.http.NameValuePair;
49 import org.apache.http.client.utils.URLEncodedUtils;
50 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
51 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
52 import org.openecomp.sdc.be.config.Configuration;
53 import org.openecomp.sdc.be.dao.api.ActionStatus;
54 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
55 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
56 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
57 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
58 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
59 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
60 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
61 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
62 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
63 import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils;
64 import org.openecomp.sdc.be.datatypes.category.CategoryDataDefinition;
65 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
66 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
67 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
68 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
69 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
70 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
71 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
72 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
73 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
74 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
75 import org.openecomp.sdc.be.externalapi.servlet.representation.VersionFilterEnum;
76 import org.openecomp.sdc.be.model.ArtifactType;
77 import org.openecomp.sdc.be.model.BaseType;
78 import org.openecomp.sdc.be.model.CatalogUpdateTimestamp;
79 import org.openecomp.sdc.be.model.Component;
80 import org.openecomp.sdc.be.model.ComponentParametersView;
81 import org.openecomp.sdc.be.model.DistributionStatusEnum;
82 import org.openecomp.sdc.be.model.LifecycleStateEnum;
83 import org.openecomp.sdc.be.model.Product;
84 import org.openecomp.sdc.be.model.PropertyScope;
85 import org.openecomp.sdc.be.model.Resource;
86 import org.openecomp.sdc.be.model.Service;
87 import org.openecomp.sdc.be.model.Tag;
88 import org.openecomp.sdc.be.model.User;
89 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
90 import org.openecomp.sdc.be.model.category.CategoryDefinition;
91 import org.openecomp.sdc.be.model.category.GroupingDefinition;
92 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
93 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
94 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
95 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
96 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
97 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
98 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
99 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
100 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
101 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
102 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
103 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
104 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
105 import org.openecomp.sdc.be.resources.data.category.CategoryData;
106 import org.openecomp.sdc.be.resources.data.category.SubCategoryData;
107 import org.openecomp.sdc.be.ui.model.UiCategories;
108 import org.openecomp.sdc.be.user.Role;
109 import org.openecomp.sdc.be.user.UserBusinessLogic;
110 import org.openecomp.sdc.common.datastructure.Wrapper;
111 import org.openecomp.sdc.common.log.wrappers.Logger;
112 import org.openecomp.sdc.common.util.ValidationUtils;
113 import org.openecomp.sdc.exception.ResponseFormat;
114 import org.springframework.beans.factory.annotation.Autowired;
116 @org.springframework.stereotype.Component("elementsBusinessLogic")
117 public class ElementBusinessLogic extends BaseBusinessLogic {
119 private static final Logger log = Logger.getLogger(ElementBusinessLogic.class);
120 private static final String SERVICES = "services";
121 private static final String RESOURCES = "resources";
122 private static final String VALIDATION_OF_USER_FAILED_USER_ID = "Validation of user failed, userId {}";
123 private static final String COMPONENT_TYPE_IS_INVALID = "Component type {} is invalid";
124 private static final String VALIDATION_OF_USER_ROLE_FAILED_USER_ID = "Validation of user role failed, userId {}";
125 private final IElementOperation elementOperation;
128 public ElementBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
129 IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic, InterfaceOperation interfaceOperation,
130 InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsOperations artifactToscaOperation,
131 IElementOperation elementOperation, UserBusinessLogic userAdminManager) {
132 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
133 artifactToscaOperation);
134 this.elementOperation = elementOperation;
141 public Either<Map<String, List<? extends Component>>, ResponseFormat> getFollowed(User user) {
142 // Used for not getting duplicated followed. Cheaper than checking ArrayList.contains
143 Either<Map<String, Set<? extends Component>>, ResponseFormat> response = null;
145 String role = user.getRole();
146 String userId = user.getUserId();
147 Role currentRole = Role.valueOf(role);
148 switch (currentRole) {
150 response = handleDesigner(userId);
152 case PRODUCT_STRATEGIST:
153 response = handleProductStrategist();
155 case PRODUCT_MANAGER:
156 response = handleProductManager(userId);
159 response = handleAdmin();
162 response = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
165 // 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)
166 return convertedToListResponse(response);
169 private Either<Map<String, List<? extends Component>>, ResponseFormat> convertedToListResponse(
170 Either<Map<String, Set<? extends Component>>, ResponseFormat> setResponse) {
171 Map<String, List<? extends Component>> arrayResponse = new HashMap<>();
172 if (setResponse.isLeft()) {
173 for (Map.Entry<String, Set<? extends Component>> entry : setResponse.left().value().entrySet()) {
174 arrayResponse.put(entry.getKey(), new ArrayList(new HashSet(entry.getValue())));
176 return Either.left(arrayResponse);
178 return Either.right(setResponse.right().value());
181 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleAdmin() {
182 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
183 // userId should stay null
184 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
185 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
186 response = getFollowedResourcesAndServices(null, lifecycleStates, new HashSet<>());
190 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleDesigner(String userId) {
191 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
192 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
193 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
194 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
195 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
196 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
198 lastStateStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
199 response = getFollowedResourcesAndServices(userId, lifecycleStates, lastStateStates);
203 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductStrategist() {
204 // Should be empty list according to Ella, 13/03/16
205 Map<String, Set<? extends Component>> result = new HashMap<>();
206 result.put("products", new HashSet<>());
207 return Either.left(result);
210 private Either<Map<String, Set<? extends Component>>, ResponseFormat> handleProductManager(String userId) {
211 Set<LifecycleStateEnum> lifecycleStates = new HashSet<>();
212 Set<LifecycleStateEnum> lastStateStates = new HashSet<>();
213 Either<Map<String, Set<? extends Component>>, ResponseFormat> response;
214 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
215 lifecycleStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
216 lifecycleStates.add(LifecycleStateEnum.CERTIFIED);
218 lastStateStates.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
219 response = getFollowedProducts(userId, lifecycleStates, lastStateStates);
223 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedResourcesAndServices(String userId,
224 Set<LifecycleStateEnum> lifecycleStates,
225 Set<LifecycleStateEnum> lastStateStates) {
227 Either<Set<Resource>, StorageOperationStatus> resources = toscaOperationFacade
228 .getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.RESOURCE);
229 if (resources.isLeft()) {
230 Either<Set<Service>, StorageOperationStatus> services = toscaOperationFacade
231 .getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.SERVICE);
232 if (services.isLeft()) {
233 Map<String, Set<? extends Component>> result = new HashMap<>();
234 result.put(SERVICES, services.left().value());
235 result.put(RESOURCES, resources.left().value());
236 return Either.left(result);
238 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(services.right().value())));
241 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(resources.right().value())));
244 janusGraphDao.commit();
248 private Either<Map<String, Set<? extends Component>>, ResponseFormat> getFollowedProducts(String userId, Set<LifecycleStateEnum> lifecycleStates,
249 Set<LifecycleStateEnum> lastStateStates) {
250 Either<Set<Product>, StorageOperationStatus> products = toscaOperationFacade
251 .getFollowed(userId, lifecycleStates, lastStateStates, ComponentTypeEnum.PRODUCT);
252 if (products.isLeft()) {
253 Map<String, Set<? extends Component>> result = new HashMap<>();
254 result.put("products", products.left().value());
255 return Either.left(result);
257 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(products.right().value())));
262 * New categories flow - start
264 public Either<List<CategoryDefinition>, ActionStatus> getAllResourceCategories() {
265 return elementOperation.getAllResourceCategories();
268 public Either<List<CategoryDefinition>, ActionStatus> getAllServiceCategories() {
269 return elementOperation.getAllServiceCategories();
272 public Either<CategoryDefinition, ResponseFormat> createCategory(CategoryDefinition category, String componentTypeParamName, String userId) {
273 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_CATEGORY;
274 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
275 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
276 CategoryTypeEnum categoryType = CategoryTypeEnum.CATEGORY;
277 User user = validateUserExists(userId);
278 if (category == null) {
279 log.debug("Category json is invalid");
280 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
281 handleCategoryAuditing(responseFormat, user, null, auditingAction, componentType);
282 return Either.right(responseFormat);
284 String categoryName = category.getName();
285 // For auditing of failures we need the original non-normalized name
286 String origCategoryName = categoryName;
287 if (componentTypeEnum == null) {
288 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
289 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
290 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
291 return Either.right(responseFormat);
293 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
294 if (validateUserRole.isRight()) {
295 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
296 ResponseFormat responseFormat = validateUserRole.right().value();
297 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
298 return Either.right(responseFormat);
300 if (!ValidationUtils.validateCategoryDisplayNameFormat(categoryName)) {
301 log.debug("Category display name format is invalid, name {}, componentType {}", categoryName, componentType);
302 ResponseFormat responseFormat = componentsUtils
303 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
304 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
305 return Either.right(responseFormat);
307 categoryName = ValidationUtils.normalizeCategoryName4Display(categoryName);
308 if (!ValidationUtils.validateCategoryDisplayNameLength(categoryName)) {
309 log.debug("Category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", categoryName,
311 ResponseFormat responseFormat = componentsUtils
312 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
313 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
314 return Either.right(responseFormat);
316 category.setName(categoryName);
317 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(categoryName);
318 category.setNormalizedName(normalizedName);
319 if (ValidationUtils.validateCategoryIconNotEmpty(category.getIcons())) {
320 log.debug("createCategory: setting category icon to default icon since service category was created without an icon ");
321 category.setIcons(Arrays.asList(DEFAULT_ICON));
323 NodeTypeEnum nodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, categoryType);
324 Either<Boolean, ActionStatus> categoryUniqueEither = elementOperation.isCategoryUniqueForType(nodeType, normalizedName);
325 if (categoryUniqueEither.isRight()) {
326 log.debug("Failed to check category uniqueness, name {}, componentType {}", categoryName, componentType);
327 ResponseFormat responseFormat = componentsUtils.getResponseFormat(categoryUniqueEither.right().value());
328 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
329 return Either.right(responseFormat);
331 Boolean isCategoryUnique = categoryUniqueEither.left().value();
332 if (Boolean.FALSE.equals(isCategoryUnique)) {
333 log.debug("Category is not unique, name {}, componentType {}", categoryName, componentType);
334 ResponseFormat responseFormat = componentsUtils
335 .getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
336 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
337 return Either.right(responseFormat);
339 Either<CategoryDefinition, ActionStatus> createCategoryByType = elementOperation.createCategory(category, nodeType);
340 if (createCategoryByType.isRight()) {
341 log.debug("Failed to create category, name {}, componentType {}", categoryName, componentType);
342 ResponseFormat responseFormat = componentsUtils
343 .getResponseFormat(ActionStatus.COMPONENT_CATEGORY_ALREADY_EXISTS, componentType, categoryName);
344 handleCategoryAuditing(responseFormat, user, origCategoryName, auditingAction, componentType);
345 return Either.right(componentsUtils.getResponseFormat(createCategoryByType.right().value()));
347 category = createCategoryByType.left().value();
348 log.debug("Created category for component {}, name {}, uniqueId {}", componentType, categoryName, category.getUniqueId());
349 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
350 handleCategoryAuditing(responseFormat, user, category.getName(), auditingAction, componentType);
351 return Either.left(category);
354 public Either<SubCategoryDefinition, ResponseFormat> createSubCategory(SubCategoryDefinition subCategory, String componentTypeParamName,
355 String parentCategoryId, String userId) {
356 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_SUB_CATEGORY;
357 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
358 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
359 CategoryTypeEnum categoryType = CategoryTypeEnum.SUBCATEGORY;
361 String parentCategoryName = parentCategoryId;
362 if (subCategory == null) {
363 log.debug("Sub-category json is invalid");
364 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
365 handleCategoryAuditing(responseFormat, null, parentCategoryName, null, auditingAction, componentType);
366 return Either.right(responseFormat);
368 String subCategoryName = subCategory.getName();
369 // For auditing of failures we need the original non-normalized name
370 String origSubCategoryName = subCategoryName;
373 user = validateUserExists(userId);
374 } catch (ByActionStatusComponentException e) {
375 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
376 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName, responseFormat);
378 } catch (ByResponseFormatComponentException e) {
379 ResponseFormat responseFormat = e.getResponseFormat();
380 handleComponentException(userId, auditingAction, componentType, parentCategoryName, origSubCategoryName, responseFormat);
383 if (componentTypeEnum == null) {
384 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
385 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
386 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
387 return Either.right(responseFormat);
389 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
390 if (validateComponentType.isRight()) {
391 log.debug("Validation of component type for sub-category failed");
392 ResponseFormat responseFormat = validateComponentType.right().value();
393 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
394 return Either.right(responseFormat);
396 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
397 if (validateUserRole.isRight()) {
398 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
399 ResponseFormat responseFormat = validateUserRole.right().value();
400 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
401 return Either.right(responseFormat);
403 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
404 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
405 CategoryDefinition categoryDefinition;
406 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(parentNodeType, parentCategoryId,
408 if (validateCategoryExists.isRight()) {
409 log.debug("Validation of parent category exists failed, parent categoryId {}", parentCategoryId);
410 ResponseFormat responseFormat = validateCategoryExists.right().value();
411 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
412 return Either.right(responseFormat);
414 categoryDefinition = validateCategoryExists.left().value();
415 parentCategoryName = categoryDefinition.getName();
416 if (!ValidationUtils.validateCategoryDisplayNameFormat(subCategoryName)) {
417 log.debug("Sub-category display name format is invalid, name {}, componentType {}", subCategoryName, componentType);
418 ResponseFormat responseFormat = componentsUtils
419 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
420 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
421 return Either.right(responseFormat);
423 subCategoryName = ValidationUtils.normalizeCategoryName4Display(subCategoryName);
424 if (!ValidationUtils.validateCategoryDisplayNameLength(subCategoryName)) {
425 log.debug("Sub-category display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", subCategoryName,
427 ResponseFormat responseFormat = componentsUtils
428 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
429 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
430 return Either.right(responseFormat);
432 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(subCategoryName);
433 subCategory.setNormalizedName(normalizedName);
434 // Uniqueness under this category
435 Either<Boolean, ActionStatus> subCategoryUniqueForCategory = elementOperation
436 .isSubCategoryUniqueForCategory(childNodeType, normalizedName, parentCategoryId);
437 if (subCategoryUniqueForCategory.isRight()) {
438 log.debug("Failed to check sub-category uniqueness, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName,
439 normalizedName, componentType);
440 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForCategory.right().value());
441 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
442 return Either.right(responseFormat);
444 Boolean isSubUnique = subCategoryUniqueForCategory.left().value();
445 if (Boolean.FALSE.equals(isSubUnique)) {
446 log.debug("Sub-category is not unique for category, parent name {}, subcategory norm name {}, componentType {}", parentCategoryName,
447 normalizedName, componentType);
448 ResponseFormat responseFormat = componentsUtils
449 .getResponseFormat(ActionStatus.COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, componentType, subCategoryName, parentCategoryName);
450 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
451 return Either.right(responseFormat);
453 // Setting name of subcategory to fit the similar subcategory name
457 // For example if Network-->kUKU exists for service category Network,
459 // and user is trying to create Router-->Kuku for service category
463 // his subcategory name will be Router-->kUKU.
464 Either<SubCategoryDefinition, ActionStatus> subCategoryUniqueForType = elementOperation
465 .getSubCategoryUniqueForType(childNodeType, normalizedName);
466 if (subCategoryUniqueForType.isRight()) {
467 log.debug("Failed validation of whether similar sub-category exists, normalizedName {} componentType {}", normalizedName, componentType);
468 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
469 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
470 return Either.right(responseFormat);
472 SubCategoryDefinition subCategoryDefinition = subCategoryUniqueForType.left().value();
473 if (subCategoryDefinition != null) {
474 subCategoryName = subCategoryDefinition.getName();
476 subCategory.setName(subCategoryName);
477 ///////////////////////////////////////////// Validations end
478 Either<SubCategoryDefinition, ActionStatus> createSubCategory = elementOperation
479 .createSubCategory(parentCategoryId, subCategory, childNodeType);
480 if (createSubCategory.isRight()) {
481 log.debug("Failed to create sub-category, name {}, componentType {}", subCategoryName, componentType);
482 ResponseFormat responseFormat = componentsUtils.getResponseFormat(subCategoryUniqueForType.right().value());
483 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
484 return Either.right(responseFormat);
486 SubCategoryDefinition subCategoryCreated = createSubCategory.left().value();
487 log.debug("Created sub-category for component {}, name {}, uniqueId {}", componentType, subCategoryName, subCategoryCreated.getUniqueId());
488 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
489 handleCategoryAuditing(responseFormat, user, parentCategoryName, subCategoryCreated.getName(), auditingAction, componentType);
490 return Either.left(subCategoryCreated);
493 private void handleComponentException(String userId, AuditingActionEnum auditingAction, String componentType, String parentCategoryName,
494 String origSubCategoryName, ResponseFormat responseFormat) {
496 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
498 user.setUserId(userId);
499 handleCategoryAuditing(responseFormat, user, parentCategoryName, origSubCategoryName, auditingAction, componentType);
502 private void handleComponentException(GroupingDefinition grouping, String userId, AuditingActionEnum auditingAction, String componentType,
503 String parentCategoryName, String parentSubCategoryName, ResponseFormat responseFormat) {
505 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
507 user.setUserId(userId);
508 String groupingNameForAudit = grouping == null ? null : grouping.getName();
509 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingNameForAudit, auditingAction, componentType);
512 private void handleComponentException(String componentType, String userId, ResponseFormat responseFormat) {
515 user.setUserId(userId);
516 log.debug(VALIDATION_OF_USER_FAILED_USER_ID, userId);
517 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
520 public Either<GroupingDefinition, ResponseFormat> createGrouping(GroupingDefinition grouping, String componentTypeParamName,
521 String grandParentCategoryId, String parentSubCategoryId, String userId) {
522 AuditingActionEnum auditingAction = AuditingActionEnum.ADD_GROUPING;
523 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
524 String componentType = componentTypeEnum == null ? componentTypeParamName : componentTypeEnum.getValue();
525 CategoryTypeEnum categoryType = CategoryTypeEnum.GROUPING;
527 String parentCategoryName = grandParentCategoryId;
528 String parentSubCategoryName = parentSubCategoryId;
531 user = validateUserExists(userId);
532 } catch (ByResponseFormatComponentException e) {
533 ResponseFormat responseFormat = e.getResponseFormat();
534 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName, parentSubCategoryName, responseFormat);
536 } catch (ByActionStatusComponentException e) {
537 ResponseFormat responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
538 handleComponentException(grouping, userId, auditingAction, componentType, parentCategoryName, parentSubCategoryName, responseFormat);
541 if (grouping == null) {
542 log.debug("Grouping json is invalid");
543 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
544 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, null, auditingAction, componentType);
545 return Either.right(responseFormat);
547 String groupingName = grouping.getName();
548 // For auditing of failures we need the original non-normalized name
549 String origGroupingName = groupingName;
550 if (componentTypeEnum == null) {
551 log.debug(COMPONENT_TYPE_IS_INVALID, componentTypeParamName);
552 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
553 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
554 return Either.right(responseFormat);
556 Either<Boolean, ResponseFormat> validateComponentType = validateComponentTypeForCategory(componentTypeEnum, categoryType);
557 if (validateComponentType.isRight()) {
558 log.debug("Validation of component type for grouping failed");
559 ResponseFormat responseFormat = validateComponentType.right().value();
560 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
561 return Either.right(responseFormat);
563 Either<Boolean, ResponseFormat> validateUserRole = validateUserRole(user, componentTypeEnum);
564 if (validateUserRole.isRight()) {
565 log.debug(VALIDATION_OF_USER_ROLE_FAILED_USER_ID, userId);
566 ResponseFormat responseFormat = validateUserRole.right().value();
567 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
568 return Either.right(responseFormat);
570 NodeTypeEnum grandParentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
571 NodeTypeEnum parentNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
572 NodeTypeEnum childNodeType = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
574 CategoryDefinition categoryDefinition;
575 Either<CategoryDefinition, ResponseFormat> validateCategoryExists = validateCategoryExists(grandParentNodeType, grandParentCategoryId,
577 if (validateCategoryExists.isRight()) {
578 log.debug("Validation of parent category exists failed, parent categoryId {}", grandParentCategoryId);
579 ResponseFormat responseFormat = validateCategoryExists.right().value();
580 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
581 return Either.right(responseFormat);
583 categoryDefinition = validateCategoryExists.left().value();
584 parentCategoryName = categoryDefinition.getName();
585 // Validate subcategory
586 SubCategoryDefinition subCategoryDefinition;
587 Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists = validateSubCategoryExists(parentNodeType, parentSubCategoryId,
589 if (validateSubCategoryExists.isRight()) {
590 log.debug("Validation of parent sub-category exists failed, parent sub-category id {}", parentSubCategoryId);
591 ResponseFormat responseFormat = validateSubCategoryExists.right().value();
592 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
593 return Either.right(responseFormat);
595 subCategoryDefinition = validateSubCategoryExists.left().value();
596 parentSubCategoryName = subCategoryDefinition.getName();
597 if (!ValidationUtils.validateCategoryDisplayNameFormat(groupingName)) {
598 log.debug("Sub-category display name format is invalid, name {}, componentType {}", groupingName, componentType);
599 ResponseFormat responseFormat = componentsUtils
600 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_FORMAT, componentType, categoryType.getValue());
601 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
602 return Either.right(responseFormat);
604 groupingName = ValidationUtils.normalizeCategoryName4Display(groupingName);
605 if (!ValidationUtils.validateCategoryDisplayNameLength(groupingName)) {
606 log.debug("Grouping display name length is invalid, should be from 4 to 25 chars, name {}, componentType {}", groupingName,
608 ResponseFormat responseFormat = componentsUtils
609 .getResponseFormat(ActionStatus.COMPONENT_ELEMENT_INVALID_NAME_LENGTH, componentType, categoryType.getValue());
610 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
611 return Either.right(responseFormat);
613 String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(groupingName);
614 grouping.setNormalizedName(normalizedName);
615 // Uniqueness under this category
616 Either<Boolean, ActionStatus> groupingUniqueForSubCategory = elementOperation
617 .isGroupingUniqueForSubCategory(childNodeType, normalizedName, parentSubCategoryId);
618 if (groupingUniqueForSubCategory.isRight()) {
619 log.debug("Failed to check grouping uniqueness, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName,
620 normalizedName, componentType);
621 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForSubCategory.right().value());
622 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
623 return Either.right(responseFormat);
625 Boolean isGroupingUnique = groupingUniqueForSubCategory.left().value();
626 if (Boolean.FALSE.equals(isGroupingUnique)) {
627 log.debug("Grouping is not unique for sub-category, parent name {}, grouping norm name {}, componentType {}", parentSubCategoryName,
628 normalizedName, componentType);
629 ResponseFormat responseFormat = componentsUtils
630 .getResponseFormat(ActionStatus.COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, componentType, groupingName, parentSubCategoryName);
631 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
632 return Either.right(responseFormat);
634 // Setting name of grouping to fit the similar grouping name ignoring
638 // For example if Network-->kUKU exists for service sub-category
640 // Network, and user is trying to create grouping Router-->Kuku for
642 // service sub-category Router,
644 // his grouping name will be Router-->kUKU.
645 Either<GroupingDefinition, ActionStatus> groupingUniqueForType = elementOperation.getGroupingUniqueForType(childNodeType, normalizedName);
646 if (groupingUniqueForType.isRight()) {
647 log.debug("Failed validation of whether similar grouping exists, normalizedName {} componentType {}", normalizedName, componentType);
648 ResponseFormat responseFormat = componentsUtils.getResponseFormat(groupingUniqueForType.right().value());
649 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
650 return Either.right(responseFormat);
652 GroupingDefinition groupingDefinition = groupingUniqueForType.left().value();
653 if (groupingDefinition != null) {
654 groupingName = groupingDefinition.getName();
656 grouping.setName(groupingName);
657 ///////////////////////////////////////////// Validations end
658 Either<GroupingDefinition, ActionStatus> createGrouping = elementOperation.createGrouping(parentSubCategoryId, grouping, childNodeType);
659 if (createGrouping.isRight()) {
660 log.debug("Failed to create grouping, name {}, componentType {}", groupingName, componentType);
661 ResponseFormat responseFormat = componentsUtils.getResponseFormat(createGrouping.right().value());
662 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, origGroupingName, auditingAction, componentType);
663 return Either.right(responseFormat);
665 GroupingDefinition groupingCreated = createGrouping.left().value();
666 log.debug("Created grouping for component {}, name {}, uniqueId {}", componentType, groupingName, groupingCreated.getUniqueId());
667 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
668 handleCategoryAuditing(responseFormat, user, parentCategoryName, parentSubCategoryName, groupingCreated.getName(), auditingAction,
670 return Either.left(groupingCreated);
673 public Either<List<CategoryDefinition>, ResponseFormat> getAllCategories(String componentType, String userId) {
674 ResponseFormat responseFormat;
675 User user = new User();
676 if (userId == null) {
677 user.setUserId("UNKNOWN");
678 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
679 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
680 return Either.right(responseFormat);
683 user = validateUserExists(userId);
684 } catch (ByActionStatusComponentException e) {
685 responseFormat = componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams());
686 handleComponentException(componentType, userId, responseFormat);
688 } catch (ByResponseFormatComponentException e) {
689 responseFormat = e.getResponseFormat();
690 handleComponentException(componentType, userId, responseFormat);
693 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
694 if (componentTypeEnum == null) {
695 log.debug("Cannot create category for component type {}", componentType);
696 responseFormat = componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "component type");
697 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
698 return Either.right(responseFormat);
700 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
701 Either<List<CategoryDefinition>, ActionStatus> getAllCategoriesByType = elementOperation.getAllCategories(nodeTypeEnum, false);
702 if (getAllCategoriesByType.isRight()) {
703 responseFormat = componentsUtils.getResponseFormat(getAllCategoriesByType.right().value());
704 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
705 return Either.right(responseFormat);
707 List<CategoryDefinition> categories = getAllCategoriesByType.left().value();
708 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
709 componentsUtils.auditGetCategoryHierarchy(user, componentType, responseFormat);
710 return Either.left(categories);
713 public Either<UiCategories, ResponseFormat> getAllCategories(String userId) {
714 ResponseFormat responseFormat;
715 UiCategories categories = new UiCategories();
716 User user = validateUserExists(userId);
717 // GET resource categories
718 Either<List<CategoryDefinition>, ActionStatus> getResourceCategoriesByType = elementOperation
719 .getAllCategories(NodeTypeEnum.ResourceNewCategory, false);
720 if (getResourceCategoriesByType.isRight()) {
721 responseFormat = componentsUtils.getResponseFormat(getResourceCategoriesByType.right().value());
722 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.RESOURCE.getValue(), responseFormat);
723 return Either.right(responseFormat);
725 categories.setResourceCategories(getResourceCategoriesByType.left().value());
726 // GET service categories
727 Either<List<CategoryDefinition>, ActionStatus> getServiceCategoriesByType = elementOperation
728 .getAllCategories(NodeTypeEnum.ServiceNewCategory, false);
729 if (getServiceCategoriesByType.isRight()) {
730 responseFormat = componentsUtils.getResponseFormat(getServiceCategoriesByType.right().value());
731 componentsUtils.auditGetCategoryHierarchy(user, ComponentTypeEnum.SERVICE.getValue(), responseFormat);
732 return Either.right(responseFormat);
734 categories.setServiceCategories(getServiceCategoriesByType.left().value());
735 categories.setProductCategories(new ArrayList<>());
736 return Either.left(categories);
739 public Either<CategoryDefinition, ResponseFormat> deleteCategory(String categoryId, String componentTypeParamName, String userId) {
740 validateUserExists(userId);
741 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
742 if (componentTypeEnum == null) {
743 log.debug("Cannot create category for component type {}", componentTypeParamName);
744 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
746 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.CATEGORY);
747 Either<CategoryDefinition, ActionStatus> deleteCategoryByType = elementOperation.deleteCategory(nodeTypeEnum, categoryId);
748 if (deleteCategoryByType.isRight()) {
749 // auditing, logging here...
750 return Either.right(componentsUtils.getResponseFormat(deleteCategoryByType.right().value()));
752 CategoryDefinition category = deleteCategoryByType.left().value();
753 log.debug("Delete category for component {}, name {}, uniqueId {}", nodeTypeEnum, category.getName(), category.getUniqueId());
754 return Either.left(category);
757 public Either<SubCategoryDefinition, ResponseFormat> deleteSubCategory(String parentSubCategoryId, String componentTypeParamName, String userId) {
758 validateUserExists(userId);
759 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
760 if (componentTypeEnum == null) {
761 log.debug("Cannot delete sub-category for component type {}", componentTypeParamName);
762 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
764 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.SUBCATEGORY);
765 Either<SubCategoryDefinition, ActionStatus> deleteSubCategoryByType = elementOperation.deleteSubCategory(nodeTypeEnum, parentSubCategoryId);
766 if (deleteSubCategoryByType.isRight()) {
767 // auditing, logging here...
768 return Either.right(componentsUtils.getResponseFormat(deleteSubCategoryByType.right().value()));
770 SubCategoryDefinition subCategory = deleteSubCategoryByType.left().value();
771 log.debug("Deleted sub-category for component {}, name {}, uniqueId {}", nodeTypeEnum, subCategory.getName(), subCategory.getUniqueId());
772 return Either.left(subCategory);
775 public Either<GroupingDefinition, ResponseFormat> deleteGrouping(String groupingId, String componentTypeParamName, String userId) {
776 validateUserExists(userId);
777 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentTypeParamName);
778 if (componentTypeEnum == null) {
779 log.debug("Cannot delete grouping for component type {}", componentTypeParamName);
780 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
782 NodeTypeEnum nodeTypeEnum = NodeTypeConvertUtils.getCategoryNodeTypeByComponentParam(componentTypeEnum, CategoryTypeEnum.GROUPING);
783 Either<GroupingDefinition, ActionStatus> deleteGroupingByType = elementOperation.deleteGrouping(nodeTypeEnum, groupingId);
784 if (deleteGroupingByType.isRight()) {
785 // auditing, logging here...
786 return Either.right(componentsUtils.getResponseFormat(deleteGroupingByType.right().value()));
788 GroupingDefinition deletedGrouping = deleteGroupingByType.left().value();
789 log.debug("Deleted grouping for component {}, name {}, uniqueId {}", nodeTypeEnum, deletedGrouping.getName(), deletedGrouping.getUniqueId());
790 return Either.left(deletedGrouping);
793 private Either<Boolean, ResponseFormat> validateUserRole(User user, ComponentTypeEnum componentTypeEnum) {
794 String role = user.getRole();
795 boolean validAdminAction =
796 role.equals(Role.ADMIN.name()) && (componentTypeEnum == ComponentTypeEnum.SERVICE || componentTypeEnum == ComponentTypeEnum.RESOURCE);
797 boolean validProductAction = role.equals(Role.PRODUCT_STRATEGIST.name()) && (componentTypeEnum == ComponentTypeEnum.PRODUCT);
798 if (!(validAdminAction || validProductAction)) {
799 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
800 log.debug("User not permitted to perform operation on category, userId = {}, role = {}, componentType = {}", user.getUserId(), role,
802 return Either.right(responseFormat);
804 return Either.left(true);
807 private Either<Boolean, ResponseFormat> validateComponentTypeForCategory(ComponentTypeEnum componentType, CategoryTypeEnum categoryType) {
808 boolean validResourceAction = componentType == ComponentTypeEnum.RESOURCE && (categoryType == CategoryTypeEnum.CATEGORY
809 || categoryType == CategoryTypeEnum.SUBCATEGORY);
810 boolean validServiceAction = componentType == ComponentTypeEnum.SERVICE && categoryType == CategoryTypeEnum.CATEGORY;
811 boolean validProductAction = componentType == ComponentTypeEnum.PRODUCT; // can
820 if (!(validResourceAction || validServiceAction || validProductAction)) {
821 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
822 log.debug("It's not allowed to create category type {} for component type {}", categoryType, componentType);
823 return Either.right(responseFormat);
825 return Either.left(true);
828 private Either<CategoryDefinition, ResponseFormat> validateCategoryExists(NodeTypeEnum nodeType, String categoryId,
829 ComponentTypeEnum componentType) {
830 Either<CategoryDefinition, ActionStatus> categoryByTypeAndId = elementOperation.getCategory(nodeType, categoryId);
831 if (categoryByTypeAndId.isRight()) {
832 log.debug("Failed to fetch parent category, parent categoryId {}", categoryId);
833 ActionStatus actionStatus = categoryByTypeAndId.right().value();
834 ResponseFormat responseFormat;
835 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
836 responseFormat = componentsUtils
837 .getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.CATEGORY.getValue(), "");
839 responseFormat = componentsUtils.getResponseFormat(actionStatus);
841 return Either.right(responseFormat);
843 return Either.left(categoryByTypeAndId.left().value());
846 private Either<SubCategoryDefinition, ResponseFormat> validateSubCategoryExists(NodeTypeEnum nodeType, String subCategoryId,
847 ComponentTypeEnum componentType) {
848 Either<SubCategoryDefinition, ActionStatus> subCategoryByTypeAndId = elementOperation.getSubCategory(nodeType, subCategoryId);
849 if (subCategoryByTypeAndId.isRight()) {
850 log.debug("Failed to fetch parent category, parent categoryId {}", subCategoryId);
851 ActionStatus actionStatus = subCategoryByTypeAndId.right().value();
852 ResponseFormat responseFormat;
853 if (actionStatus == ActionStatus.COMPONENT_CATEGORY_NOT_FOUND) {
854 responseFormat = componentsUtils
855 .getResponseFormat(actionStatus, componentType.getValue().toLowerCase(), CategoryTypeEnum.SUBCATEGORY.getValue(), "");
857 responseFormat = componentsUtils.getResponseFormat(actionStatus);
859 return Either.right(responseFormat);
861 return Either.left(subCategoryByTypeAndId.left().value());
864 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, AuditingActionEnum auditingAction,
865 String componentType) {
866 componentsUtils.auditCategory(responseFormat, user, category, null, null, auditingAction, componentType);
869 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory,
870 AuditingActionEnum auditingAction, String componentType) {
871 componentsUtils.auditCategory(responseFormat, user, category, subCategory, null, auditingAction, componentType);
874 private void handleCategoryAuditing(ResponseFormat responseFormat, User user, String category, String subCategory, String grouping,
875 AuditingActionEnum auditingAction, String componentType) {
876 componentsUtils.auditCategory(responseFormat, user, category, subCategory, grouping, auditingAction, componentType);
880 * New categories flow - end
882 public Either<List<Tag>, ActionStatus> getAllTags(String userId) {
883 ActionStatus status = validateUserExistsActionStatus(userId);
884 if (ActionStatus.OK != status) {
885 return Either.right(status);
887 return elementOperation.getAllTags();
890 public Either<List<PropertyScope>, ActionStatus> getAllPropertyScopes(String userId) {
891 ActionStatus status = validateUserExistsActionStatus(userId);
892 if (ActionStatus.OK != status) {
893 return Either.right(status);
895 return elementOperation.getAllPropertyScopes();
898 public Either<List<ArtifactType>, ActionStatus> getAllArtifactTypes(final String userId) {
899 ActionStatus status = validateUserExistsActionStatus(userId);
900 if (ActionStatus.OK != status) {
901 return Either.right(status);
903 return Either.left(elementOperation.getAllArtifactTypes());
906 public Either<Configuration.HeatDeploymentArtifactTimeout, ActionStatus> getDefaultHeatTimeout() {
907 return elementOperation.getDefaultHeatTimeout();
910 public Either<Map<String, List<CatalogComponent>>, ResponseFormat> getCatalogComponents(List<OriginTypeEnum> excludeTypes) {
912 return toscaOperationFacade.getCatalogOrArchiveComponents(true, excludeTypes)
913 .bimap(this::groupByComponentType, err -> componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(err)));
915 janusGraphDao.commit();
919 private Map<String, List<CatalogComponent>> groupByComponentType(List<CatalogComponent> components) {
920 Map<String, List<CatalogComponent>> map = components.stream()
921 .collect(Collectors.groupingBy(cmpt -> cmptTypeToString(cmpt.getComponentType())));
922 // fixed response for UI!!! UI need to receive always map!
924 map = new HashMap<>();
926 map.computeIfAbsent(RESOURCES, k -> new ArrayList());
927 map.computeIfAbsent(SERVICES, k -> new ArrayList());
931 private String cmptTypeToString(ComponentTypeEnum componentTypeEnum) {
932 switch (componentTypeEnum) {
938 throw new IllegalStateException("resources or services only");
942 public Either<List<? extends Component>, ResponseFormat> getFilteredCatalogComponents(String assetType, Map<FilterKeyEnum, Object> filters,
944 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
946 Optional<NameValuePair> invalidFilter = findInvalidFilter(query, assetTypeEnum);
947 if (invalidFilter.isPresent()) {
948 log.debug("getFilteredAssetList: invalid filter key");
949 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_FILTER_KEY, invalidFilter.get().getName(),
950 FilterKeyEnum.getValidFiltersByAssetType(assetTypeEnum).toString()));
953 if (MapUtils.isEmpty(filters)) {
954 Either<List<Component>, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, null, false);
955 if (componentsList.isRight()) {
956 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value())));
958 return Either.left(componentsList.left().value());
960 Either<List<Component>, StorageOperationStatus> result = getFilteredComponents(filters, assetTypeEnum, false);
961 // category hierarchy mismatch or category/subCategory/distributionStatus not found
962 if (result.isRight()) {
963 List<String> params = getErrorResponseParams(filters, assetTypeEnum);
964 return Either.right(componentsUtils
965 .getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value()), params.get(0), params.get(1), params.get(2)));
967 if (result.left().value().isEmpty()) { // no assets found for requested criteria
968 return Either.right(componentsUtils.getResponseFormat(ActionStatus.NO_ASSETS_FOUND, assetType, query));
970 return Either.left(result.left().value());
973 private Either<List<Component>, StorageOperationStatus> getFilteredComponents(Map<FilterKeyEnum, Object> filters, ComponentTypeEnum assetType,
974 boolean inTransaction) {
975 Either<List<Component>, StorageOperationStatus> assetResult = Either.left(new LinkedList<>());
976 if (assetType == ComponentTypeEnum.RESOURCE) {
977 assetResult = getFilteredResources(filters, inTransaction);
978 } else if (assetType == ComponentTypeEnum.SERVICE) {
979 assetResult = getFilteredServices(filters);
984 private <T extends Component> Either<List<T>, StorageOperationStatus> getFilteredServices(Map<FilterKeyEnum, Object> filters) {
985 final String distributionStatus = (String) filters.get(FilterKeyEnum.DISTRIBUTION_STATUS);
986 final DistributionStatusEnum distEnum;
987 if (StringUtils.isNotBlank(distributionStatus)) {
988 distEnum = DistributionStatusEnum.findState(distributionStatus);
989 if (distEnum == null) {
990 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
995 Either<List<Service>, StorageOperationStatus> components = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.SERVICE, null, false);
996 if (components.isRight()) { // not found == empty list
997 return Either.left(new ArrayList<>());
999 final String categoryName = (String) filters.get(FilterKeyEnum.CATEGORY);
1000 Predicate<Service> servPredicate = Component::isService;
1001 if (StringUtils.isNotBlank(categoryName)) { // primary filter
1002 servPredicate = servPredicate.and(
1003 p -> p.getCategories().parallelStream().map(CategoryDataDefinition::getName).collect(Collectors.toList()).contains(categoryName));
1005 if (distEnum != null) {// secondary filter
1006 servPredicate = servPredicate.and(p -> p.getDistributionStatus() == distEnum);
1008 List<Service> serviceList = components.left().value().parallelStream().filter(servPredicate).collect(Collectors.toList());
1010 final String version = (String) filters.get(FilterKeyEnum.VERSION);
1011 if (StringUtils.isNotBlank(version)) {
1012 serviceList = filterServicesWithVersion(serviceList, version);
1014 final List<String> metadata = (List<String>) filters.get(FilterKeyEnum.METADATA);
1015 if (CollectionUtils.isNotEmpty(metadata)) {
1016 serviceList = filterServicesWithMetadata(serviceList, metadata);
1018 return Either.left((List<T>) serviceList);
1021 private List<Service> filterServicesWithMetadata(final List<Service> serviceList, final List<String> metadata) {
1022 Predicate<Service> predicate = Component::isService;
1023 final String regex = "[\\w\\.\\- ]";
1024 for (final String keyValuePair : metadata) {
1025 final Matcher matcher = Pattern.compile("(" + regex + "+)[:=](" + regex + "+)").matcher(keyValuePair);
1026 if (matcher.find()) {
1027 predicate = predicate.and(service -> matcher.group(2).equals(service.getCategorySpecificMetadata().get(matcher.group(1))));
1030 return serviceList.stream().filter(predicate).collect(Collectors.toList());
1033 private List<Service> filterServicesWithVersion(final List<Service> serviceList, final String version) {
1034 String trim = version.trim();
1035 final Optional<VersionFilterEnum> versionFilter = VersionFilterEnum.getFilter(trim);
1036 if (versionFilter.isPresent()) {
1037 return versionFilter.get().filter(serviceList, trim);
1042 public Either<List<? extends Component>, ResponseFormat> getCatalogComponentsByUuidAndAssetType(String assetType, String uuid) {
1043 if (assetType == null || uuid == null) {
1044 log.debug("getCatalogComponentsByUuidAndAssetType: One of the function parameteres is null");
1045 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1047 ComponentTypeEnum assetTypeEnum = AssetTypeEnum.convertToComponentTypeEnum(assetType);
1048 if (assetTypeEnum == null) {
1049 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not found");
1050 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1052 Map<GraphPropertyEnum, Object> additionalPropertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
1053 switch (assetTypeEnum) {
1055 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
1058 additionalPropertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
1061 log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API");
1062 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1064 Either<List<Component>, StorageOperationStatus> componentsListByUuid = toscaOperationFacade
1065 .getComponentListByUuid(uuid, additionalPropertiesToMatch);
1066 if (componentsListByUuid.isRight()) {
1067 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + " fetching failed");
1068 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum);
1069 return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid));
1071 log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful");
1072 return Either.left(componentsListByUuid.left().value());
1075 public List<String> getAllComponentTypesParamNames() {
1076 List<String> paramNames = new ArrayList<>();
1077 paramNames.add(ComponentTypeEnum.SERVICE_PARAM_NAME);
1078 paramNames.add(ComponentTypeEnum.RESOURCE_PARAM_NAME);
1079 paramNames.add(ComponentTypeEnum.PRODUCT_PARAM_NAME);
1083 public List<String> getAllSupportedRoles() {
1084 Role[] values = Role.values();
1085 List<String> roleNames = new ArrayList<>();
1086 for (Role role : values) {
1087 roleNames.add(role.name());
1092 public Either<Map<String, String>, ActionStatus> getResourceTypesMap() {
1093 return elementOperation.getResourceTypesMap();
1096 private Optional<NameValuePair> findInvalidFilter(String query, ComponentTypeEnum assetType) {
1097 return URLEncodedUtils.parse(query, StandardCharsets.UTF_8)
1098 .stream().filter(p -> !FilterKeyEnum.getValidFiltersByAssetType(assetType).contains(p.getName())).findAny();
1101 private List<String> getErrorResponseParams(Map<FilterKeyEnum, Object> filters, ComponentTypeEnum assetType) {
1102 List<String> params = new ArrayList<>();
1103 if (1 == filters.size()) {
1104 params.add(assetType.getValue().toLowerCase());
1105 params.add(filters.keySet().iterator().next().getName());
1106 params.add((String) filters.values().iterator().next());
1108 params.add(assetType.getValue());
1109 params.add((String) filters.get(FilterKeyEnum.SUB_CATEGORY));
1110 params.add((String) filters.get(FilterKeyEnum.CATEGORY));
1115 public Either<List<Component>, StorageOperationStatus> getFilteredResources(Map<FilterKeyEnum, Object> filters, boolean inTransaction) {
1116 String subCategoryName = (String) filters.get(FilterKeyEnum.SUB_CATEGORY);
1117 String categoryName = (String) filters.get(FilterKeyEnum.CATEGORY);
1118 ResourceTypeEnum resourceType = ResourceTypeEnum.getType((String) filters.get(FilterKeyEnum.RESOURCE_TYPE));
1119 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> subcategories = null;
1120 Optional<ImmutablePair<SubCategoryData, GraphEdge>> subCategoryData;
1121 if (categoryName != null) {
1122 subcategories = getAllSubCategories(categoryName);
1123 if (subcategories.isRight()) {
1124 filters.remove(FilterKeyEnum.SUB_CATEGORY);
1125 return Either.right(subcategories.right().value());
1128 if (subCategoryName != null) { // primary filter
1129 if (categoryName != null) {
1130 subCategoryData = validateCategoryHierarcy(subcategories.left().value(), subCategoryName);
1131 if (subCategoryData.isEmpty()) {
1132 return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1134 return fetchByCategoryOrSubCategoryUid(subCategoryData.get().getLeft().getUniqueId(), NodeTypeEnum.Resource, inTransaction,
1137 return fetchByCategoryOrSubCategoryName(subCategoryName, NodeTypeEnum.ResourceSubcategory, NodeTypeEnum.Resource, inTransaction,
1140 if (subcategories != null) {
1141 return fetchByMainCategory(subcategories.left().value(), inTransaction, resourceType);
1143 return fetchComponentMetaDataByResourceType((String) filters.get(FilterKeyEnum.RESOURCE_TYPE), inTransaction);
1146 private Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, StorageOperationStatus> getAllSubCategories(String categoryName) {
1147 Either<CategoryData, StorageOperationStatus> categoryResult = elementOperation
1148 .getNewCategoryData(categoryName, NodeTypeEnum.ResourceNewCategory, CategoryData.class);
1149 if (categoryResult.isRight()) {
1150 return Either.right(categoryResult.right().value());
1152 CategoryData categoryData = categoryResult.left().value();
1153 Either<List<ImmutablePair<SubCategoryData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
1154 .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ResourceNewCategory), categoryData.getUniqueId(),
1155 GraphEdgeLabels.SUB_CATEGORY, NodeTypeEnum.ResourceSubcategory, SubCategoryData.class);
1156 if (childrenNodes.isRight()) {
1157 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(childrenNodes.right().value()));
1159 return Either.left(childrenNodes.left().value());
1162 private Optional<ImmutablePair<SubCategoryData, GraphEdge>> validateCategoryHierarcy(List<ImmutablePair<SubCategoryData, GraphEdge>> childNodes,
1163 String subCategoryName) {
1164 Predicate<ImmutablePair<SubCategoryData, GraphEdge>> matchName = p -> p.getLeft().getSubCategoryDataDefinition().getName()
1165 .equals(subCategoryName);
1166 return childNodes.stream().filter(matchName).findAny();
1169 protected <T extends Component> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryUid(String categoryUid,
1170 NodeTypeEnum categoryType,
1171 boolean inTransaction,
1172 ResourceTypeEnum resourceType) {
1174 return collectComponents(categoryType, categoryUid, resourceType);
1176 if (!inTransaction) {
1177 janusGraphDao.commit();
1182 protected <T extends Component> Either<List<T>, StorageOperationStatus> fetchByCategoryOrSubCategoryName(String categoryName,
1183 NodeTypeEnum categoryType,
1184 NodeTypeEnum neededType,
1185 boolean inTransaction,
1186 ResourceTypeEnum resourceType) {
1187 List<T> components = new ArrayList<>();
1189 Class<? extends GraphNode> categoryClazz = categoryType == NodeTypeEnum.ServiceNewCategory ? CategoryData.class : SubCategoryData.class;
1190 Map<String, Object> props = new HashMap<>();
1191 props.put(GraphPropertiesDictionary.NORMALIZED_NAME.getProperty(), ValidationUtils.normalizeCategoryName4Uniqueness(categoryName));
1192 Either<List<GraphNode>, JanusGraphOperationStatus> getCategory = janusGraphGenericDao.getByCriteria(categoryType, props,
1193 (Class<GraphNode>) categoryClazz);
1194 if (getCategory.isRight()) {
1195 return Either.right(StorageOperationStatus.CATEGORY_NOT_FOUND);
1197 for (GraphNode category : getCategory.left().value()) {
1198 Either<List<T>, StorageOperationStatus> result = collectComponents(neededType, category.getUniqueId(), resourceType);
1199 if (result.isRight() && result.right().value() != StorageOperationStatus.NOT_FOUND) {
1201 } else if (result.isLeft()) {
1202 components.addAll(result.left().value());
1205 if (components.isEmpty()) {
1206 return Either.right(StorageOperationStatus.NOT_FOUND);
1208 return Either.left(components);
1210 if (!inTransaction) {
1211 janusGraphDao.commit();
1216 private <T extends Component> Either<List<T>, StorageOperationStatus> collectComponents(NodeTypeEnum neededType, String categoryUid,
1217 ResourceTypeEnum resourceType) {
1218 List<T> components = new ArrayList<>();
1219 Either<GraphVertex, JanusGraphOperationStatus> categoryVertexById = janusGraphDao.getVertexById(categoryUid, JsonParseFlagEnum.NoParse);
1220 if (categoryVertexById.isRight()) {
1221 JanusGraphOperationStatus status = categoryVertexById.right().value();
1222 log.debug("#collectComponents Failed to get category vertex with uid {}, status is {}.", categoryUid, status);
1223 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1225 GraphVertex categoryVertex = categoryVertexById.left().value();
1226 Either<List<GraphVertex>, JanusGraphOperationStatus> componentsVertices = janusGraphDao
1227 .getParentVertices(categoryVertex, EdgeLabelEnum.CATEGORY, JsonParseFlagEnum.ParseMetadata);
1228 if (componentsVertices.isRight()) {
1229 JanusGraphOperationStatus status = componentsVertices.right().value();
1230 log.debug("#collectComponents Failed to get components vertices of category {}, status is {}.", categoryVertex, status);
1231 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
1233 List<ComponentMetadataDataDefinition> componentsMetadataDataDefinition = componentsVertices.left().value().stream().filter(Objects::nonNull)
1234 .filter(componentsVertex -> Objects.nonNull(componentsVertex.getType())).map(ModelConverter::convertToComponentMetadataDataDefinition)
1235 .collect(Collectors.toList());
1236 for (ComponentMetadataDataDefinition component : componentsMetadataDataDefinition) {
1237 boolean isHighest = isTrue(component.isHighestVersion());
1238 boolean isMatchingResourceType = isMatchingByResourceType(neededType, resourceType, component);
1239 boolean isDeleted = isTrue(component.isDeleted());
1240 boolean isArchived = isTrue(component.isArchived());
1241 if (isHighest && isMatchingResourceType && !isDeleted && !isArchived) {
1242 Either<T, StorageOperationStatus> result = toscaOperationFacade
1243 .getToscaElement(component.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
1244 if (result.isRight()) {
1245 return Either.right(result.right().value());
1247 components.add(result.left().value());
1250 return Either.left(components);
1253 private boolean isMatchingByResourceType(NodeTypeEnum componentType, ResourceTypeEnum resourceType,
1254 ComponentMetadataDataDefinition componentData) {
1256 if (componentType == NodeTypeEnum.Resource) {
1257 if (resourceType == null) {
1260 isMatching = resourceType == ((ResourceMetadataDataDefinition) componentData).getResourceType();
1268 private <T extends Component> Either<List<T>, StorageOperationStatus> fetchByMainCategory(
1269 List<ImmutablePair<SubCategoryData, GraphEdge>> subcategories, boolean inTransaction, ResourceTypeEnum resourceType) {
1270 List<T> components = new ArrayList<>();
1271 for (ImmutablePair<SubCategoryData, GraphEdge> subCategory : subcategories) {
1272 Either<List<T>, StorageOperationStatus> fetched = fetchByCategoryOrSubCategoryUid(subCategory.getLeft().getUniqueId(),
1273 NodeTypeEnum.Resource, inTransaction, resourceType);
1274 if (fetched.isRight()) {
1277 components.addAll(fetched.left().value());
1279 return Either.left(components);
1282 private Either<List<Component>, StorageOperationStatus> fetchComponentMetaDataByResourceType(String resourceType, boolean inTransaction) {
1283 List<Component> components = null;
1284 StorageOperationStatus status;
1285 Wrapper<StorageOperationStatus> statusWrapper = new Wrapper<>();
1287 ComponentParametersView fetchUsersAndCategoriesFilter = new ComponentParametersView(
1288 Arrays.asList(ComponentFieldsEnum.USERS.getValue(), ComponentFieldsEnum.CATEGORIES.getValue()));
1289 Either<List<Component>, StorageOperationStatus> getResources = toscaOperationFacade
1290 .fetchMetaDataByResourceType(resourceType, fetchUsersAndCategoriesFilter);
1291 if (getResources.isRight()) {
1292 status = getResources.right().value();
1293 if (status != StorageOperationStatus.NOT_FOUND) {
1294 statusWrapper.setInnerElement(getResources.right().value());
1296 components = new ArrayList<>();
1299 components = getResources.left().value();
1301 if (statusWrapper.isEmpty()) {
1302 return Either.left(components);
1304 return Either.right(statusWrapper.getInnerElement());
1307 if (!inTransaction) {
1308 janusGraphDao.commit();
1313 public CatalogUpdateTimestamp getCatalogUpdateTime() {
1315 return toscaOperationFacade.getCatalogTimes();
1317 janusGraphDao.commit();
1321 public Either<List<BaseType>, ActionStatus> getBaseTypes(final String categoryName, final String userId, final String modelName) {
1322 final ActionStatus status = validateUserExistsActionStatus(userId);
1323 if (ActionStatus.OK != status) {
1324 return Either.right(status);
1326 return Either.left(elementOperation.getServiceBaseTypes(categoryName, modelName));
1330 * Checks if a category requires a base type.
1332 * @param categoryName the category name
1333 * @return {@code true} if a base type is required, {@code false} otherwise.
1335 public boolean isBaseTypeRequired(final String categoryName) {
1336 return elementOperation.isBaseTypeRequired(categoryName);
1340 * Fetches default baseType from the template.
1342 * @param categoryName the category name
1343 * @return defaultBaseType mapped to the corresponding category name.
1345 public String getDefaultBaseType(final String categoryName) {
1346 return elementOperation.getDefaultBaseType(categoryName);
1349 public boolean isDoNotExtendBaseType(final String categoryName) {
1350 return elementOperation.isDoNotExtendBaseType(categoryName);