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=========================================================
21 package org.openecomp.sdc.be.components.impl;
23 import fj.data.Either;
24 import org.apache.commons.collections.CollectionUtils;
25 import org.apache.commons.collections.MapUtils;
26 import org.apache.commons.io.FilenameUtils;
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.commons.lang3.math.NumberUtils;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
31 import org.openecomp.sdc.be.components.utils.Utils;
32 import org.openecomp.sdc.be.components.validation.AccessValidations;
33 import org.openecomp.sdc.be.components.validation.ComponentValidations;
34 import org.openecomp.sdc.be.config.BeEcompErrorManager;
35 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
36 import org.openecomp.sdc.be.config.ConfigurationManager;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
39 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
40 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
41 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
42 import org.openecomp.sdc.be.info.ArtifactDefinitionInfo;
43 import org.openecomp.sdc.be.info.ArtifactTemplateInfo;
44 import org.openecomp.sdc.be.info.GroupDefinitionInfo;
45 import org.openecomp.sdc.be.model.ArtifactDefinition;
46 import org.openecomp.sdc.be.model.Component;
47 import org.openecomp.sdc.be.model.ComponentInstance;
48 import org.openecomp.sdc.be.model.ComponentParametersView;
49 import org.openecomp.sdc.be.model.DataTypeDefinition;
50 import org.openecomp.sdc.be.model.GroupDefinition;
51 import org.openecomp.sdc.be.model.GroupInstance;
52 import org.openecomp.sdc.be.model.GroupInstanceProperty;
53 import org.openecomp.sdc.be.model.GroupProperty;
54 import org.openecomp.sdc.be.model.GroupTypeDefinition;
55 import org.openecomp.sdc.be.model.PropertyDefinition;
56 import org.openecomp.sdc.be.model.PropertyDefinition.GroupInstancePropertyValueUpdateBehavior;
57 import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames;
58 import org.openecomp.sdc.be.model.Resource;
59 import org.openecomp.sdc.be.model.User;
60 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
61 import org.openecomp.sdc.be.model.jsontitan.operations.ArtifactsOperations;
62 import org.openecomp.sdc.be.model.jsontitan.operations.GroupsOperation;
63 import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation;
64 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
65 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
66 import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
67 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
68 import org.openecomp.sdc.common.api.Constants;
69 import org.openecomp.sdc.common.util.ValidationUtils;
70 import org.openecomp.sdc.exception.ResponseFormat;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73 import org.springframework.beans.factory.annotation.Autowired;
75 import java.util.ArrayList;
76 import java.util.Arrays;
77 import java.util.Collection;
78 import java.util.Collections;
79 import java.util.EnumMap;
80 import java.util.HashMap;
81 import java.util.List;
83 import java.util.Map.Entry;
84 import java.util.Optional;
86 import java.util.regex.Pattern;
87 import java.util.stream.Collectors;
89 import static java.util.stream.Collectors.toList;
91 @org.springframework.stereotype.Component("groupBusinessLogic")
92 public class GroupBusinessLogic extends BaseBusinessLogic {
93 public static final String GROUP_DELIMITER_REGEX = "\\.\\.";
94 private static String ADDING_GROUP = "AddingGroup";
96 public static final String INITIAL_VERSION = "1";
98 private static final String CREATE_GROUP = "CreateGroup";
100 private static final String UPDATE_GROUP = "UpdateGroup";
102 private static final String GET_GROUP = "GetGroup";
104 private static final String DELETE_GROUP = "GetGroup";
106 private static final Logger log = LoggerFactory.getLogger(GroupBusinessLogic.class);
108 @javax.annotation.Resource
109 private AccessValidations accessValidations;
111 @javax.annotation.Resource
112 private GroupTypeOperation groupTypeOperation;
115 private ArtifactsOperations artifactsOperation;
118 private GroupsOperation groupsOperation;
120 private ApplicationDataTypeCache dataTypeCache;
122 private String getComponentTypeForResponse(org.openecomp.sdc.be.model.Component component) {
123 String componentTypeForResponse = "SERVICE";
124 if (component instanceof Resource) {
125 componentTypeForResponse = ((Resource) component).getResourceType().name();
127 return componentTypeForResponse;
131 * Verify that the artifact members belongs to the component
137 private Either<Boolean, ResponseFormat> verifyArtifactsBelongsToComponent(Component component, List<String> artifacts, String context) {
139 if (CollectionUtils.isEmpty(artifacts)) {
140 return Either.left(true);
143 Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
144 if (MapUtils.isEmpty(deploymentArtifacts)) {
145 BeEcompErrorManager.getInstance().logInvalidInputError(context, "No deployment artifact found under component " + component.getNormalizedName(), ErrorSeverity.INFO);
146 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
149 List<String> currentArtifacts = deploymentArtifacts.values().stream().map(p -> p.getUniqueId()).collect(toList());
150 log.debug("The deployment artifacts of component {} are {}", component.getNormalizedName(), deploymentArtifacts);
151 if (!currentArtifacts.containsAll(artifacts)) {
152 BeEcompErrorManager.getInstance().logInvalidInputError(context, "Not all artifacts belongs to component " + component.getNormalizedName(), ErrorSeverity.INFO);
153 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
156 return Either.left(true);
161 * verify that the members are component instances of the component
164 * @param groupMembers
165 * @param memberToscaTypes
168 private Either<Boolean, ResponseFormat> verifyComponentInstancesAreValidMembers(Component component, String groupName, Map<String, String> groupMembers, List<String> memberToscaTypes) {
170 if (MapUtils.isEmpty(groupMembers)) {
171 return Either.left(true);
174 if (CollectionUtils.isEmpty(memberToscaTypes)) {
175 return Either.left(true);
178 List<ComponentInstance> componentInstances = component.getComponentInstances();
179 if (CollectionUtils.isNotEmpty(componentInstances)) {
180 Map<String, ComponentInstance> compInstUidToCompInstMap = componentInstances.stream().collect(Collectors.toMap(p -> p.getUniqueId(), p -> p));
182 Set<String> allCompInstances = compInstUidToCompInstMap.keySet();
184 for (Entry<String, String> groupMember : groupMembers.entrySet()) {
185 String compName = groupMember.getKey();
186 String compUid = groupMember.getValue();
188 if (!allCompInstances.contains(compUid)) {
190 * %1 - member name %2 - group name %3 - VF name %4 - component type [VF ]
192 String componentTypeForResponse = getComponentTypeForResponse(component);
194 BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "Not all group members exists under the component", ErrorSeverity.INFO);
195 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, compName, groupName, component.getNormalizedName(), componentTypeForResponse));
200 return Either.left(true);
206 * Update GroupDefinition metadata
210 * @param componentType
211 * @param updatedGroup
212 * @param inTransaction
215 public Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(String componentId, User user, ComponentTypeEnum componentType, GroupDefinition updatedGroup, boolean inTransaction , boolean shouldLock) {
217 Either<GroupDefinition, ResponseFormat> result = null;
219 // Validate user exist
220 Either<User, ResponseFormat> validateUserExists = validateUserExists(user.getUserId(), UPDATE_GROUP, inTransaction);
221 if (validateUserExists.isRight()) {
222 result = Either.right(validateUserExists.right().value());
225 // Validate component exist
226 Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(componentId, componentType, null);
227 if (validateComponent.isRight()) {
228 result = Either.right(validateComponent.right().value());
231 org.openecomp.sdc.be.model.Component component = validateComponent.left().value();
232 // validate we can work on component
233 Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, user.getUserId());
234 if (canWork.isRight()) {
235 result = Either.right(canWork.right().value());
238 List<GroupDefinition> currentGroups = component.getGroups();
239 if (CollectionUtils.isEmpty(currentGroups)) {
240 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(), component.getName(), ActionStatus.GROUP_IS_MISSING);
241 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(), component.getComponentType().getValue()));
244 // Validate groups exists in the component
245 Optional<GroupDefinition> currentGroupOpt = currentGroups.stream().filter(g -> g.getUniqueId().equals(updatedGroup.getUniqueId())).findAny();
246 if (!currentGroupOpt.isPresent()) {
247 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(), component.getName(), ActionStatus.GROUP_IS_MISSING);
248 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(), component.getComponentType().getValue()));
251 GroupDefinition currentGroup = currentGroupOpt.get();
253 Either<Boolean, ResponseFormat> lockResult = lockComponent(componentId, component, "Update GroupDefinition Metadata");
254 if (lockResult.isRight()) {
255 result = Either.right(lockResult.right().value());
259 // Validate group type is vfModule
260 if (currentGroup.getType().equals(Constants.GROUP_TOSCA_HEAT)) {
261 log.error("Failed to update the metadata of group {}. Group type is {} and cannot be updated", currentGroup.getName(), currentGroup.getType());
262 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, updatedGroup.getType());
263 result = Either.right(responseFormat);
266 result = updateGroupMetadata(component, currentGroup, updatedGroup);
270 if (result.isLeft()) {
276 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
281 private Either<GroupDefinition, ResponseFormat> updateGroupMetadata(Component component, GroupDefinition currentGroup, GroupDefinition updatedGroup) {
282 String currentGroupName = currentGroup.getName();
283 Either<GroupDefinition, ResponseFormat> result = validateAndUpdateGroupMetadata(currentGroup, updatedGroup);
285 if (result.isRight()) {
286 log.debug("Failed to validate a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
288 if (result.isLeft()) {
289 result = updateGroup(component, currentGroup, currentGroupName);
294 private Either<GroupDefinition, ResponseFormat> updateGroup(Component component, GroupDefinition updatedGroup, String currentGroupName) {
295 Either<GroupDefinition, StorageOperationStatus> handleGroupRes;
296 Either<GroupDefinition, ResponseFormat> result = null;
297 if (updatedGroup.getName().equals(currentGroupName)) {
298 handleGroupRes = groupsOperation.updateGroup(component, updatedGroup);
299 if (handleGroupRes.isRight()) {
300 log.debug("Failed to update a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
301 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(handleGroupRes.right().value())));
304 StorageOperationStatus deleteStatus = groupsOperation.deleteGroup(component, currentGroupName);
305 if (deleteStatus != StorageOperationStatus.OK) {
306 log.debug("Failed to delete the group {} from component {}. ", updatedGroup.getName(), component.getName());
307 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteStatus)));
309 handleGroupRes = groupsOperation.addGroup(component, updatedGroup);
310 if (handleGroupRes.isRight()) {
311 log.debug("Failed to add the group {} to component {}. ", updatedGroup.getName(), component.getName());
312 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(handleGroupRes.right().value())));
315 if (result == null) {
316 result = Either.left(updatedGroup);
322 * Validate and Update Group Property
325 * @param groupUniqueId
327 * @param componentType
328 * @param groupPropertiesToUpdate
329 * @param inTransaction
332 public Either<List<GroupProperty>, ResponseFormat> validateAndUpdateGroupProperties(String componentId, String groupUniqueId, User user, ComponentTypeEnum componentType, List<GroupProperty> groupPropertiesToUpdate, boolean inTransaction) {
334 Either<List<GroupProperty>, ResponseFormat> result = Either.left(groupPropertiesToUpdate);
336 Optional<GroupDefinition> optionalGroupConnectedToVf = null;
337 GroupDefinition currentGroup = null;
338 StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, componentType.getNodeType());
339 if (lockResult != StorageOperationStatus.OK) {
340 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockResult, componentType), componentId));
342 if (result.isLeft()) {
343 // VF exist because lock succedded
344 Resource vf = (Resource) toscaOperationFacade.getToscaElement(componentId).left().value();
345 optionalGroupConnectedToVf =
346 // All groups on resource
347 vf.getGroups().stream().
348 // Filter in group sent is part of VF groups
349 filter(e -> e.getUniqueId().equals(groupUniqueId)).
352 if (!optionalGroupConnectedToVf.isPresent()) {
353 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, groupUniqueId, vf.getName(), ComponentTypeEnum.RESOURCE.getValue()));
357 if (result.isLeft()) {
358 currentGroup = optionalGroupConnectedToVf.get();
359 result = validateGroupPropertyAndResetEmptyValue(currentGroup, groupPropertiesToUpdate);
361 if (result.isLeft()) {
362 result = updateGroupPropertiesValue(componentId, currentGroup, groupPropertiesToUpdate, inTransaction);
363 if (result.isRight()) {
364 BeEcompErrorManager.getInstance().logBeSystemError("Update GroupProperties");
365 log.debug("failed to update Vf {}", componentId);
369 } catch (Exception e) {
370 log.debug("Error in validateAndUpdateGroupProperty {}", e);
371 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
373 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
378 private void resetEmptyValueWithDefaults(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
379 Map<String, GroupProperty> originalProperties =
380 // Stream of original properties from group
381 originalGroup.convertToGroupProperties().stream().
382 // Collecting to map with name as key
383 collect(Collectors.toMap(e -> e.getName(), e -> e));
384 for (GroupProperty gp : groupPropertiesToUpdate) {
385 if (StringUtils.isEmpty(gp.getValue())) {
386 gp.setValue(originalProperties.get(gp.getName()).getDefaultValue());
392 private Either<List<GroupProperty>, ResponseFormat> validateGroupPropertyAndResetEmptyValue(GroupDefinition originalGroup, List<GroupProperty> groupPropertiesToUpdate) {
394 Either<List<GroupProperty>, ResponseFormat> ret = validateOnlyValueChanged(groupPropertiesToUpdate, originalGroup);
396 resetEmptyValueWithDefaults(groupPropertiesToUpdate, originalGroup);
399 // Validate Type Match Value
400 Optional<StorageOperationStatus> optionalError =
401 // Stream of group properties
402 groupPropertiesToUpdate.stream().
403 // Validate each and map to returned Strorage status value
404 map(e -> groupOperation.validateAndUpdatePropertyValue(e)).
405 // Keep only failed result if there is such
406 filter(e -> e != StorageOperationStatus.OK).
409 if (optionalError.isPresent()) {
410 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(optionalError.get());
411 ret = Either.right(componentsUtils.getResponseFormat(actionStatus));
416 // Validate min max ect...
417 ret = validatePropertyBusinessLogic(groupPropertiesToUpdate, originalGroup);
423 private Either<List<GroupProperty>, ResponseFormat> validatePropertyBusinessLogic(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
425 Either<List<GroupProperty>, ResponseFormat> ret = Either.left(groupPropertiesToUpdate);
427 Map<PropertyNames, String> nameValueMap = new HashMap<>();
428 for (GroupProperty gp : groupPropertiesToUpdate) {
429 // Filter out non special properties which does not have Enum
430 final PropertyNames gpEnum = PropertyNames.findName(gp.getName());
431 if (gpEnum != null) {
432 nameValueMap.put(gpEnum, gp.getValue());
436 if (!MapUtils.isEmpty(nameValueMap)) {
438 if (nameValueMap.containsKey(PropertyNames.INITIAL_COUNT) || nameValueMap.containsKey(PropertyNames.MAX_INSTANCES) || nameValueMap.containsKey(PropertyNames.MIN_INSTANCES)) {
440 Map<PropertyNames, String> oldValueMap = prepareMapWithOriginalProperties(originalGroup);
442 Either<Boolean, ResponseFormat> eitherValid = validateMinMaxAndInitialCountPropertyLogicVF(nameValueMap, oldValueMap);
443 if (eitherValid.isRight()) {
444 ret = Either.right(eitherValid.right().value());
447 if (ret.isLeft() && (nameValueMap.containsKey(PropertyNames.VF_MODULE_DESCRIPTION) || nameValueMap.containsKey(PropertyNames.VF_MODULE_LABEL))) {
449 Optional<ResponseFormat> optionalError =
450 // Stream of group Properties
451 groupPropertiesToUpdate.stream().
452 // Filter in only properties that needs text validation
453 filter(e -> enumHasValueFilter(e.getName(), enumName -> PropertyNames.findName(enumName), PropertyNames.VF_MODULE_DESCRIPTION, PropertyNames.VF_MODULE_LABEL)).
454 // validate text properties
455 map(e -> validateFreeText(e)).
456 // filter in only errors if exist
457 filter(e -> e.isRight()).
458 // map the Either value to the Error
459 map(e -> e.right().value())
462 if (optionalError.isPresent()) {
463 ret = Either.right(optionalError.get());
472 private Map<PropertyNames, String> prepareMapWithOriginalProperties(GroupDefinition originalGroup) {
473 Map<PropertyNames, String> oldValueMap = new HashMap<>();
474 PropertyNames[] propertiesToCheck = new PropertyNames[] { PropertyNames.INITIAL_COUNT, PropertyNames.MAX_INSTANCES, PropertyNames.MIN_INSTANCES };
476 for (GroupProperty gp : originalGroup.convertToGroupProperties()) {
477 if (enumHasValueFilter(gp.getName(), PropertyNames::findName, propertiesToCheck)) {
478 oldValueMap.put(PropertyNames.findName(gp.getName()), gp.getValue());
481 if (StringUtils.isEmpty(oldValueMap.get(PropertyNames.MAX_INSTANCES))) {
482 oldValueMap.put(PropertyNames.MAX_INSTANCES, String.valueOf(Integer.MAX_VALUE));
487 private Either<List<GroupProperty>, ResponseFormat> validateOnlyValueChanged(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
489 Either<List<GroupProperty>, ResponseFormat> ret = Either.left(groupPropertiesToUpdate);
490 if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) {
491 ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY));
492 } else if (CollectionUtils.isEmpty(originalGroup.getProperties())) {
493 ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, groupPropertiesToUpdate.get(NumberUtils.INTEGER_ZERO).getName()));
495 Map<String, GroupProperty> namePropertyMap =
496 // Original Group Properties Stream
497 originalGroup.convertToGroupProperties().stream().
498 // Collect to map with name as key
499 collect(Collectors.toMap(e -> e.getName(), e -> e));
501 Optional<GroupProperty> optionalMissingProperty =
502 // Group Properties to be updated Stream
503 groupPropertiesToUpdate.stream().
504 // Filter in property that is not contained in original if there is such
505 filter(e -> !namePropertyMap.containsKey(e.getName())).
509 if (optionalMissingProperty.isPresent()) {
510 ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, optionalMissingProperty.get().getName()));
512 Optional<GroupProperty> optionalNonValueChange =
513 // groups to be updated stream
514 groupPropertiesToUpdate.stream().
515 // filter in only properties with non-value (illegal) change
516 filter(e -> !isOnlyGroupPropertyValueChanged(e, namePropertyMap.get(e.getName()))).
519 if (optionalNonValueChange.isPresent()) {
520 ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY, optionalNonValueChange.get().getName()));
530 * if groupProperty are the same or if only value is different returns true, otherwise returns false.
532 * @param groupProperty
533 * @param groupProperty2
536 private boolean isOnlyGroupPropertyValueChanged(GroupProperty groupProperty, GroupProperty groupProperty2) {
537 // Create 2 duplicates for groupPropery and reset their values
539 GroupProperty groupPropertyDuplicate = new GroupProperty(groupProperty);
540 groupPropertyDuplicate.setValue(null);
541 groupPropertyDuplicate.setSchema(null);
542 groupPropertyDuplicate.setParentUniqueId(null);
543 GroupProperty groupProperty2Duplicate = new GroupProperty(groupProperty2);
544 groupProperty2Duplicate.setValue(null);
545 groupProperty2Duplicate.setSchema(null);
546 groupProperty2Duplicate.setParentUniqueId(null);
547 return groupPropertyDuplicate.equals(groupProperty2Duplicate) && StringUtils.equals(groupPropertyDuplicate.getValueUniqueUid(), groupProperty2Duplicate.getValueUniqueUid());
548 } catch (Exception e) {
549 log.debug("Failed validate group properties. ", e);
555 * Validate and update GroupDefinition metadata
557 * @param currentGroup
561 private Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
562 // Check if to update, and update GroupDefinition name.
563 Either<Boolean, ResponseFormat> response = validateAndUpdateGroupName(currentGroup, groupUpdate);
564 if (response.isRight()) {
565 ResponseFormat errorResponse = response.right().value();
566 return Either.right(errorResponse);
569 // Do not allow to update GroupDefinition version directly.
570 String versionUpdated = groupUpdate.getVersion();
571 String versionCurrent = currentGroup.getVersion();
572 if (versionUpdated != null && !versionCurrent.equals(versionUpdated)) {
573 log.info("update Group: recived request to update version to {} the field is not updatable ignoring.", versionUpdated);
576 return Either.left(currentGroup);
580 * Validate and update GroupDefinition name
582 * @param currentGroup
586 private Either<Boolean, ResponseFormat> validateAndUpdateGroupName(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
587 String nameUpdated = groupUpdate.getName();
588 String nameCurrent = currentGroup.getName();
589 if (!nameCurrent.equals(nameUpdated)) {
590 Either<Boolean, ResponseFormat> validatNameResponse = validateGroupName(currentGroup.getName(), groupUpdate.getName() ,true);
591 if (validatNameResponse.isRight()) {
592 ResponseFormat errorRespons = validatNameResponse.right().value();
593 return Either.right(errorRespons);
595 currentGroup.setName(groupUpdate.getName());
597 return Either.left(true);
601 * Validate that group name to update is valid (same as current group name except for middle part). For example: Current group name: MyResource..MyDesc..Module-1 Group to update: MyResource..MyDesc2..Module-1 Verify that only the second part
602 * MyDesc was changed.
604 * @param currentGroupName
605 * @param groupUpdateName
608 private Either<Boolean, ResponseFormat> validateGroupName(String currentGroupName, String groupUpdateName , boolean isforceNameModification) {
610 // Check if the group name is in old format.
611 if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupUpdateName).matches()) {
612 log.error("Group name {} is in old format", groupUpdateName);
613 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME, groupUpdateName));
616 // Check that name pats 1 and 3 did not changed (only the second
617 // part can be changed)
618 // But verify before that the current group format is the new one
619 if (!Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(currentGroupName).matches()) {
620 String[] split1 = currentGroupName.split(GROUP_DELIMITER_REGEX);
621 String currentResourceName = split1[0];
622 String currentCounter = split1[2];
624 String[] split2 = groupUpdateName.split(GROUP_DELIMITER_REGEX);
625 String groupUpdateResourceName = split2[0];
626 String groupUpdateCounter = split2[2];
627 if (!isforceNameModification){ //if not forced ,allow name prefix&suffix validation [no changes]
628 if (!currentResourceName.equals(groupUpdateResourceName)) {
629 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentResourceName));
632 if (!currentCounter.equals(groupUpdateCounter)) {
633 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentCounter));
639 return Either.left(true);
640 } catch (Exception e) {
641 log.error("Error valiadting group name", e);
642 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
648 * associate artifacts to a given group
652 * @param componentType
653 * @param inTransaction
656 public Either<GroupDefinitionInfo, ResponseFormat> getGroupWithArtifactsById(ComponentTypeEnum componentType, String componentId, String groupId, String userId, boolean inTransaction) {
658 Either<GroupDefinitionInfo, ResponseFormat> result = null;
660 // Validate user exist
661 Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, GET_GROUP, true);
663 if (validateUserExists.isRight()) {
664 result = Either.right(validateUserExists.right().value());
668 // Validate component exist
669 org.openecomp.sdc.be.model.Component component = null;
670 String realComponentId = componentId;
673 ComponentParametersView componentParametersView = new ComponentParametersView();
674 componentParametersView.disableAll();
675 componentParametersView.setIgnoreGroups(false);
676 componentParametersView.setIgnoreArtifacts(false);
677 componentParametersView.setIgnoreUsers(false);
679 Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
680 if (validateComponent.isRight()) {
681 result = Either.right(validateComponent.right().value());
684 component = validateComponent.left().value();
686 Either<GroupDefinition, StorageOperationStatus> groupEither = findGroupOnComponent(component, groupId);
688 if (groupEither.isRight()) {
689 log.debug("Faild to find group {} under component {}", groupId, component.getUniqueId());
690 BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "group " + groupId + " not found under component " + component.getUniqueId(), ErrorSeverity.INFO);
691 String componentTypeForResponse = getComponentTypeForResponse(component);
692 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, groupId, component.getSystemName(), componentTypeForResponse));
695 GroupDefinition group = groupEither.left().value();
697 Boolean isBase = null;
698 List<GroupProperty> props = group.convertToGroupProperties();
699 if (props != null && !props.isEmpty()) {
700 Optional<GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
701 if (isBasePropOp.isPresent()) {
702 GroupProperty propIsBase = isBasePropOp.get();
703 isBase = Boolean.parseBoolean(propIsBase.getValue());
706 BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
710 List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
711 List<ArtifactDefinition> artifactsFromComponent = new ArrayList<>();
712 List<String> artifactsIds = group.getArtifacts();
714 Map<String, ArtifactDefinition> deploymentArtifacts = null;
715 if (MapUtils.isNotEmpty(component.getDeploymentArtifacts())) {
716 deploymentArtifacts = component.getDeploymentArtifacts().values().stream().collect(Collectors.toMap(a -> a.getUniqueId(), a -> a));
719 if (artifactsIds != null && !artifactsIds.isEmpty()) {
720 for (String id : artifactsIds) {
721 if (MapUtils.isEmpty(deploymentArtifacts) || !deploymentArtifacts.containsKey(id)) {
722 log.debug("Failed to get artifact {} . Status is {} ", id, StorageOperationStatus.NOT_FOUND);
723 ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND));
724 result = Either.right(responseFormat);
727 artifactsFromComponent.add(deploymentArtifacts.get(id));
729 if (!artifactsFromComponent.isEmpty()) {
730 for (ArtifactDefinition artifactDefinition : artifactsFromComponent) {
731 ArtifactDefinitionInfo artifactDefinitionInfo = new ArtifactDefinitionInfo(artifactDefinition);
732 artifacts.add(artifactDefinitionInfo);
737 GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
738 resultInfo.setIsBase(isBase);
739 if (!artifacts.isEmpty()) {
740 resultInfo.setArtifacts(artifacts);
742 result = Either.left(resultInfo);
748 if (!inTransaction) {
750 if (result == null || result.isRight()) {
751 log.debug("Going to execute rollback on create group.");
754 log.debug("Going to execute commit on create group.");
764 private Either<GroupDefinition, StorageOperationStatus> findGroupOnComponent(Component component, String groupId) {
766 Either<GroupDefinition, StorageOperationStatus> result = null;
767 if (CollectionUtils.isNotEmpty(component.getGroups())) {
768 Optional<GroupDefinition> foundGroup = component.getGroups().stream().filter(g -> g.getUniqueId().equals(groupId)).findFirst();
769 if (foundGroup.isPresent()) {
770 result = Either.left(foundGroup.get());
773 if (result == null) {
774 result = Either.right(StorageOperationStatus.NOT_FOUND);
779 public String getAsString(List<String> list) {
781 if (list == null || list.isEmpty()) {
784 StringBuilder builder = new StringBuilder();
785 list.forEach(p -> builder.append(p + ","));
787 String result = builder.toString();
788 return result.substring(0, result.length());
793 private Either<List<GroupProperty>, ResponseFormat> updateGroupPropertiesValue(String componentId, GroupDefinition currentGroup, List<GroupProperty> groupPropertyToUpdate, boolean inTransaction) {
794 Either<List<GroupProperty>, ResponseFormat> result;
796 Either<List<GroupProperty>, StorageOperationStatus> eitherUpdate = groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, groupPropertyToUpdate);
797 if (eitherUpdate.isRight()) {
798 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(eitherUpdate.right().value());
799 result = Either.right(componentsUtils.getResponseFormat(actionStatus));
801 result = Either.left(eitherUpdate.left().value());
806 public Either<Boolean, ResponseFormat> validateGenerateVfModuleGroupNames(List<ArtifactTemplateInfo> allGroups, String resourceSystemName, int startGroupCounter) {
807 Either<Boolean, ResponseFormat> validateGenerateGroupNamesRes = Either.left(true);
808 Collections.sort(allGroups, (art1, art2) -> ArtifactTemplateInfo.compareByGroupName(art1, art2));
809 for (ArtifactTemplateInfo group : allGroups) {
810 Either<String, ResponseFormat> validateGenerateGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, group.getDescription(), startGroupCounter++);
811 if (validateGenerateGroupNameRes.isRight()) {
812 validateGenerateGroupNamesRes = Either.right(validateGenerateGroupNameRes.right().value());
815 group.setGroupName(validateGenerateGroupNameRes.left().value());
817 return validateGenerateGroupNamesRes;
821 * Generate module name from resourceName, description and counter
823 * @param resourceSystemName
825 * @param groupCounter
828 private Either<String, ResponseFormat> validateGenerateVfModuleGroupName(String resourceSystemName, String description, int groupCounter) {
829 Either<String, ResponseFormat> validateGenerateGroupNameRes;
830 if (resourceSystemName != null && description != null && Pattern.compile(Constants.MODULE_DESC_PATTERN).matcher(description).matches()) {
831 final String fileName = description.replaceAll(GROUP_DELIMITER_REGEX, "\\.");
832 validateGenerateGroupNameRes = Either.left(String.format(Constants.MODULE_NAME_FORMAT, resourceSystemName, FilenameUtils.removeExtension(fileName), groupCounter));
834 validateGenerateGroupNameRes = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME));
836 return validateGenerateGroupNameRes;
839 public Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNames(Map<String, GroupDefinition> groups, String resourceSystemName) {
841 Map<String, GroupDefinition> updatedNamesGroups = new HashMap<>();
842 Either<Map<String, GroupDefinition>, ResponseFormat> result = Either.left(updatedNamesGroups);
843 for (Entry<String, GroupDefinition> groupEntry : groups.entrySet()) {
844 GroupDefinition curGroup = groupEntry.getValue();
845 String groupType = curGroup.getType();
846 String groupName = groupEntry.getKey();
849 Either<String, ResponseFormat> newGroupNameRes;
850 if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && !Pattern.compile(Constants.MODULE_NEW_NAME_PATTERN).matcher(groupName).matches()) {
852 if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupEntry.getKey()).matches()) {
853 counter = Integer.parseInt(groupEntry.getKey().split(Constants.MODULE_NAME_DELIMITER)[1]);
854 description = curGroup.getDescription();
856 counter = getNextVfModuleNameCounter(updatedNamesGroups);
857 description = groupName;
859 newGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, description, counter);
860 if (newGroupNameRes.isRight()) {
861 log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
862 result = Either.right(newGroupNameRes.right().value());
865 groupName = newGroupNameRes.left().value();
866 curGroup.setName(groupName);
868 updatedNamesGroups.put(groupName, curGroup);
873 public int getNextVfModuleNameCounter(Map<String, GroupDefinition> groups) {
875 if (groups != null && !groups.isEmpty()) {
876 counter = getNextVfModuleNameCounter(groups.values());
881 public int getNextVfModuleNameCounter(Collection<GroupDefinition> groups) {
883 if (groups != null && !groups.isEmpty()) {
884 List<Integer> counters = groups.stream().filter(group -> Pattern.compile(Constants.MODULE_NEW_NAME_PATTERN).matcher(group.getName()).matches() || Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(group.getName()).matches())
885 .map(group -> Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1])).collect(toList());
886 counter = (counters == null || counters.isEmpty()) ? 0 : counters.stream().max((a, b) -> Integer.compare(a, b)).get() + 1;
891 public Either<List<GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesOnGraph(List<GroupDefinition> groups, Component component, boolean inTransaction) {
892 List<GroupDefinition> updatedGroups = new ArrayList<>();
893 Either<List<GroupDefinition>, ResponseFormat> result = Either.left(updatedGroups);
895 for (GroupDefinition group : groups) {
896 String groupType = group.getType();
897 String oldGroupName = group.getName();
899 Either<String, ResponseFormat> newGroupNameRes;
901 if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(oldGroupName).matches()) {
902 counter = Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1]);
903 newGroupNameRes = validateGenerateVfModuleGroupName(component.getSystemName(), group.getDescription(), counter);
904 if (newGroupNameRes.isRight()) {
905 log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
906 result = Either.right(newGroupNameRes.right().value());
909 newGroupName = newGroupNameRes.left().value();
910 group.setName(newGroupName);
913 updatedGroups.add(group);
917 result = Either.left(updatedGroups);
922 public Either<GroupDefinitionInfo, ResponseFormat> getGroupInstWithArtifactsById(ComponentTypeEnum componentType, String componentId, String componentInstanceId, String groupInstId, String userId, boolean inTransaction) {
923 Either<GroupDefinitionInfo, ResponseFormat> result = null;
925 // Validate user exist
926 Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, UPDATE_GROUP, true);
928 if (validateUserExists.isRight()) {
929 result = Either.right(validateUserExists.right().value());
933 // Validate component exist
934 org.openecomp.sdc.be.model.Component component = null;
935 String realComponentId = componentId;
938 ComponentParametersView componentParametersView = new ComponentParametersView();
939 componentParametersView.disableAll();
940 componentParametersView.setIgnoreUsers(false);
941 componentParametersView.setIgnoreComponentInstances(false);
942 componentParametersView.setIgnoreArtifacts(false);
944 Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
945 if (validateComponent.isRight()) {
946 result = Either.right(validateComponent.right().value());
949 component = validateComponent.left().value();
950 Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceRes = findComponentInstanceAndGroupInstanceOnComponent(component, componentInstanceId, groupInstId);
952 if (findComponentInstanceAndGroupInstanceRes.isRight()) {
953 log.debug("Failed to get group {} . Status is {} ", groupInstId, findComponentInstanceAndGroupInstanceRes.right().value());
954 ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(findComponentInstanceAndGroupInstanceRes.right().value()));
955 result = Either.right(responseFormat);
959 GroupInstance group = findComponentInstanceAndGroupInstanceRes.left().value().getRight();
961 Boolean isBase = null;
962 List<? extends GroupProperty> props = group.convertToGroupInstancesProperties();
963 if (props != null && !props.isEmpty()) {
964 Optional<? extends GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
965 if (isBasePropOp.isPresent()) {
966 GroupProperty propIsBase = isBasePropOp.get();
967 isBase = Boolean.parseBoolean(propIsBase.getValue());
970 BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
974 List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
975 List<String> artifactsIds = group.getArtifacts();
976 if (artifactsIds != null && !artifactsIds.isEmpty()) {
978 List<ComponentInstance> instances = component.getComponentInstances();
979 if (instances != null) {
980 Optional<ComponentInstance> findFirst = instances.stream().filter(i -> i.getUniqueId().equals(componentInstanceId)).findFirst();
981 if (findFirst.isPresent()) {
982 ComponentInstance ci = findFirst.get();
983 Map<String, ArtifactDefinition> deploymentArtifacts = ci.getDeploymentArtifacts();
984 for (String id : artifactsIds) {
985 Optional<ArtifactDefinition> artOp = deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst();
986 if (artOp.isPresent()) {
987 artifacts.add(new ArtifactDefinitionInfo(artOp.get()));
990 List<String> instArtifactsIds = group.getGroupInstanceArtifacts();
991 for (String id : instArtifactsIds) {
992 Optional<ArtifactDefinition> artOp = deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst();
993 if (artOp.isPresent()) {
994 artifacts.add(new ArtifactDefinitionInfo(artOp.get()));
1001 GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
1002 resultInfo.setIsBase(isBase);
1003 if (!artifacts.isEmpty()) {
1004 resultInfo.setArtifacts(artifacts);
1006 result = Either.left(resultInfo);
1012 if (!inTransaction) {
1014 if (result == null || result.isRight()) {
1015 log.debug("Going to execute rollback on create group.");
1016 titanDao.rollback();
1018 log.debug("Going to execute commit on create group.");
1027 private Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceOnComponent(Component component, String componentInstanceId, String groupInstId) {
1029 Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> result = null;
1030 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
1031 Optional<GroupInstance> foundGroup;
1032 Optional<ComponentInstance> foundComponent = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(componentInstanceId)).findFirst();
1033 if (foundComponent.isPresent() && CollectionUtils.isNotEmpty(foundComponent.get().getGroupInstances())) {
1034 foundGroup = foundComponent.get().getGroupInstances().stream().filter(gi -> gi.getUniqueId().equals(groupInstId)).findFirst();
1035 if (foundGroup.isPresent()) {
1036 result = Either.left(new ImmutablePair<>(foundComponent.get(), foundGroup.get()));
1040 if (result == null) {
1041 result = Either.right(StorageOperationStatus.NOT_FOUND);
1046 private int getLatestIntProperty(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues, PropertyNames propertyKey) {
1048 if (newValues.containsKey(propertyKey)) {
1049 value = newValues.get(propertyKey);
1051 value = parentValues.get(propertyKey);
1053 return Integer.valueOf(value);
1056 private boolean isPropertyChanged(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues, final PropertyNames minInstances) {
1057 return newValues.containsKey(minInstances) && !newValues.get(minInstances).equals(parentValues.get(minInstances));
1060 private Either<Boolean, ResponseFormat> validateMinMaxAndInitialCountPropertyLogicVF(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues) {
1062 int latestMaxInstances = getLatestIntProperty(newValues, parentValues, PropertyNames.MAX_INSTANCES);
1063 int latestInitialCount = getLatestIntProperty(newValues, parentValues, PropertyNames.INITIAL_COUNT);
1064 int latestMinInstances = getLatestIntProperty(newValues, parentValues, PropertyNames.MIN_INSTANCES);
1065 Either<Boolean, ResponseFormat> result = Either.left(true);
1067 if (isPropertyChanged(newValues, parentValues, PropertyNames.INITIAL_COUNT) && result.isLeft()
1068 && (latestInitialCount > latestMaxInstances || latestInitialCount < latestMinInstances)) {
1069 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE, PropertyNames.INITIAL_COUNT.getPropertyName(), String.valueOf(latestMinInstances), String.valueOf(latestMaxInstances)));
1071 if (isPropertyChanged(newValues, parentValues, PropertyNames.MAX_INSTANCES) && result.isLeft() &&
1072 latestMaxInstances < latestInitialCount) {
1073 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyNames.MAX_INSTANCES.getPropertyName(), "higher", String.valueOf(latestInitialCount)));
1075 if (isPropertyChanged(newValues, parentValues, PropertyNames.MIN_INSTANCES) &&
1076 result.isLeft() && latestMinInstances > latestInitialCount) {
1077 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyNames.MIN_INSTANCES.getPropertyName(), "lower", String.valueOf(latestInitialCount)));
1082 private Either<Boolean, ResponseFormat> validateMinMaxAndInitialCountPropertyLogic(Map<PropertyNames, String> newValues, Map<PropertyNames, String> currValues, Map<PropertyNames, String> parentValues) {
1084 Either<Boolean, ResponseFormat> result;
1085 for (Entry<PropertyNames, String> entry : newValues.entrySet()) {
1086 PropertyNames currPropertyName = entry.getKey();
1087 if (currPropertyName == PropertyNames.MIN_INSTANCES) {
1088 String minValue = parentValues.get(PropertyNames.MIN_INSTANCES);
1089 String maxValue = newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MAX_INSTANCES) : currValues.get(PropertyNames.INITIAL_COUNT);
1090 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1091 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1092 if (result.isRight()) {
1095 } else if (currPropertyName == PropertyNames.INITIAL_COUNT) {
1096 String minValue = newValues.containsKey(PropertyNames.MIN_INSTANCES) ? newValues.get(PropertyNames.MIN_INSTANCES) : currValues.get(PropertyNames.MIN_INSTANCES);
1097 String maxValue = newValues.containsKey(PropertyNames.MAX_INSTANCES) ? newValues.get(PropertyNames.MAX_INSTANCES) : currValues.get(PropertyNames.MAX_INSTANCES);
1098 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1099 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1100 if (result.isRight()) {
1103 } else if (currPropertyName == PropertyNames.MAX_INSTANCES) {
1104 String minValue = newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MIN_INSTANCES) : currValues.get(PropertyNames.INITIAL_COUNT);
1105 String maxValue = parentValues.get(PropertyNames.MAX_INSTANCES);
1106 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1107 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1108 if (result.isRight()) {
1113 return Either.left(true);
1116 private Either<Boolean, ResponseFormat> validateValueInRange(ImmutablePair<PropertyNames, String> newValue, ImmutablePair<PropertyNames, String> min, ImmutablePair<PropertyNames, String> max) {
1117 Either<Boolean, ResponseFormat> result;
1118 final String warnMessage = "Failed to validate {} as property value of {}. It must be not higher than {}, and not lower than {}.";
1119 int newValueInt = parseIntValue(newValue.getValue(), newValue.getKey());
1120 int minInt = parseIntValue(min.getValue(), min.getKey());
1121 int maxInt = parseIntValue(max.getValue(), max.getKey());
1122 if (newValueInt < 0 || minInt < 0 || maxInt < 0) {
1123 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY));
1124 } else if (newValueInt < minInt || newValueInt > maxInt) {
1125 log.debug(warnMessage, newValue.getValue(), newValue.getKey().getPropertyName(), min.getValue(), max.getValue());
1127 .right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_MIN_MAX_INSTANCES_PROPERTY_VALUE, newValue.getKey().getPropertyName(), maxInt == Integer.MAX_VALUE ? Constants.UNBOUNDED : max.getValue(), min.getValue()));
1129 result = Either.left(true);
1134 private int parseIntValue(String value, PropertyNames propertyName) {
1136 if (propertyName == PropertyNames.MAX_INSTANCES) {
1137 result = convertIfUnboundMax(value);
1138 } else if (NumberUtils.isNumber(value)) {
1139 result = Integer.parseInt(value);
1147 * validates received new property values and updates group instance in case of success
1149 * @param oldGroupInstance
1150 * @param newProperties
1151 * @param inTransaction
1154 public Either<GroupInstance, ResponseFormat> validateAndUpdateGroupInstancePropertyValues(String componentId, String instanceId, GroupInstance oldGroupInstance, List<GroupInstanceProperty> newProperties, boolean inTransaction) {
1156 Either<GroupInstance, ResponseFormat> actionResult = null;
1157 Either<GroupInstance, StorageOperationStatus> updateGroupInstanceResult = null;
1158 Either<List<GroupInstanceProperty>, ResponseFormat> validateRes = validateReduceGroupInstancePropertiesBeforeUpdate(oldGroupInstance, newProperties);
1159 if (validateRes.isRight()) {
1160 log.debug("Failed to validate group instance {} properties before update. ", oldGroupInstance.getName());
1161 actionResult = Either.right(validateRes.right().value());
1163 if (actionResult == null) {
1164 List<GroupInstanceProperty> validatedReducedNewProperties = validateRes.left().value();
1165 updateGroupInstanceResult = groupsOperation.updateGroupInstancePropertyValuesOnGraph(componentId, instanceId, oldGroupInstance, validatedReducedNewProperties);
1166 if (updateGroupInstanceResult.isRight()) {
1167 log.debug("Failed to update group instance {} property values. ", oldGroupInstance.getName());
1168 actionResult = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateGroupInstanceResult.right().value())));
1171 if (actionResult == null) {
1172 actionResult = Either.left(updateGroupInstanceResult.left().value());
1174 return actionResult;
1177 private Either<List<GroupInstanceProperty>, ResponseFormat> validateReduceGroupInstancePropertiesBeforeUpdate(GroupInstance oldGroupInstance, List<GroupInstanceProperty> newProperties) {
1179 Either<Boolean, ResponseFormat> validationRes = null;
1180 Either<List<GroupInstanceProperty>, ResponseFormat> actionResult;
1181 Map<String, GroupInstanceProperty> existingProperties = oldGroupInstance.convertToGroupInstancesProperties().stream().collect(Collectors.toMap(p -> p.getName(), p -> p));
1182 Map<PropertyNames, String> newPropertyValues = new EnumMap<>(PropertyNames.class);
1183 List<GroupInstanceProperty> reducedProperties = new ArrayList<>();
1184 String currPropertyName;
1186 for (GroupInstanceProperty currNewProperty : newProperties) {
1187 currPropertyName = currNewProperty.getName();
1188 validationRes = handleAndAddProperty(reducedProperties, newPropertyValues, currNewProperty, existingProperties.get(currPropertyName));
1189 if (validationRes.isRight()) {
1190 log.debug("Failed to handle property {} of group instance {}. ", currPropertyName, oldGroupInstance.getName());
1194 if (validationRes == null || validationRes.isLeft()) {
1195 Map<PropertyNames, String> existingPropertyValues = new EnumMap<>(PropertyNames.class);
1196 Map<PropertyNames, String> parentPropertyValues = new EnumMap<>(PropertyNames.class);
1197 fillValuesAndParentValuesFromExistingProperties(existingProperties, existingPropertyValues, parentPropertyValues);
1198 validationRes = validateMinMaxAndInitialCountPropertyLogic(newPropertyValues, existingPropertyValues, parentPropertyValues);
1200 if (validationRes.isLeft()) {
1201 actionResult = Either.left(reducedProperties);
1203 actionResult = Either.right(validationRes.right().value());
1205 } catch (Exception e) {
1206 log.error("Exception occured during validation and reducing group instance properties. The message is {}", e.getMessage(), e);
1207 actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1209 return actionResult;
1212 private void fillValuesAndParentValuesFromExistingProperties(Map<String, GroupInstanceProperty> existingProperties, Map<PropertyNames, String> propertyValues, Map<PropertyNames, String> parentPropertyValues) {
1213 PropertyNames[] allPropertyNames = PropertyNames.values();
1214 for (PropertyNames name : allPropertyNames) {
1215 if (isUpdatable(name)) {
1216 propertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getValue()));
1217 parentPropertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getParentValue()));
1222 private Either<Boolean, ResponseFormat> handleAndAddProperty(List<GroupInstanceProperty> reducedProperties, Map<PropertyNames, String> newPropertyValues, GroupInstanceProperty currNewProperty, GroupInstanceProperty currExistingProperty) {
1224 Either<Boolean, ResponseFormat> validationRes = null;
1225 String currPropertyName = currNewProperty.getName();
1226 PropertyNames propertyName = PropertyNames.findName(currPropertyName);
1228 if (currExistingProperty == null) {
1229 log.warn("The value of property with the name {} cannot be updated. The property not found on group instance. ", currPropertyName);
1230 } else if (isUpdatable(propertyName)) {
1231 validationRes = validateAndUpdatePropertyValue(currNewProperty, currExistingProperty);
1232 if (validationRes.isRight()) {
1233 log.debug("Failed to validate property value {} of property {}. ", currNewProperty.getValue(), currPropertyName);
1235 addPropertyUpdatedValues(reducedProperties, propertyName, newPropertyValues, currNewProperty, currExistingProperty);
1238 validateImmutableProperty(currExistingProperty, currNewProperty);
1240 if (validationRes == null) {
1241 validationRes = Either.left(true);
1243 } catch (Exception e) {
1244 log.error("Exception occured during handle and adding property. The message is {}", e.getMessage(), e);
1245 validationRes = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1247 return validationRes;
1250 private boolean isUpdatable(PropertyNames updatablePropertyName) {
1251 return updatablePropertyName != null && updatablePropertyName.getUpdateBehavior().getLevelNumber() >= GroupInstancePropertyValueUpdateBehavior.UPDATABLE_ON_SERVICE_LEVEL.getLevelNumber();
1254 private void addPropertyUpdatedValues(List<GroupInstanceProperty> reducedProperties, PropertyNames propertyName, Map<PropertyNames, String> newPropertyValues, GroupInstanceProperty newProperty, GroupInstanceProperty existingProperty) {
1256 String newValue = newProperty.getValue();
1257 if (!newValue.equals(String.valueOf(existingProperty.getValue()))) {
1258 newProperty.setValueUniqueUid(existingProperty.getValueUniqueUid());
1259 reducedProperties.add(newProperty);
1261 if (!isEmptyMinInitialCountValue(propertyName, newValue)) {
1262 newPropertyValues.put(propertyName, newValue);
1266 private boolean isEmptyMinInitialCountValue(PropertyNames propertyName, String newValue) {
1267 boolean result = false;
1268 if ((propertyName == PropertyNames.MIN_INSTANCES || propertyName == PropertyNames.INITIAL_COUNT) && !NumberUtils.isNumber(newValue)) {
1274 private int convertIfUnboundMax(String value) {
1277 if (!NumberUtils.isNumber(value)) {
1278 result = Integer.MAX_VALUE;
1280 result = Integer.parseInt(value);
1285 private Either<Boolean, ResponseFormat> validateAndUpdatePropertyValue(GroupInstanceProperty newProperty, GroupInstanceProperty existingProperty) {
1287 Either<Boolean, ResponseFormat> validationRes = null;
1288 String parentValue = existingProperty.getParentValue();
1290 newProperty.setParentValue(parentValue);
1291 if (StringUtils.isEmpty(newProperty.getValue())) {
1292 newProperty.setValue(parentValue);
1294 if (StringUtils.isEmpty(existingProperty.getValue())) {
1295 existingProperty.setValue(parentValue);
1297 StorageOperationStatus status = groupOperation.validateAndUpdatePropertyValue(newProperty);
1298 if (status != StorageOperationStatus.OK) {
1299 log.debug("Failed to validate property value {} of property with name {}. Status is {}. ", newProperty.getValue(), newProperty.getName(), status);
1300 validationRes = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status)));
1302 if (validationRes == null) {
1303 validationRes = Either.left(true);
1305 return validationRes;
1308 private void validateImmutableProperty(GroupProperty oldProperty, GroupProperty newProperty) {
1309 if (oldProperty.getValue() == null && newProperty.getValue() != null || oldProperty.getValue() != null && !oldProperty.getValue().equals(newProperty.getValue())) {
1310 log.warn("The value of property with the name {} cannot be updated on service level. Going to ignore new property value {}. ", oldProperty.getName(), newProperty.getValue());
1314 public GroupDefinition createGroup(String groupType, ComponentTypeEnum componentTypeEnum, String componentId,
1318 Component component = accessValidations.validateUserCanWorkOnComponentAndLockIt(componentTypeEnum, componentId, userId, CREATE_GROUP);
1320 validateGroupTypePerComponent(groupType, component);
1322 GroupTypeDefinition groupTypeDefinition = groupTypeOperation.getLatestGroupTypeByType(groupType, false)
1324 .on(se -> onGroupTypeNotFound(component));
1326 boolean isFirstGroup = component.getGroups() == null;
1327 GroupDefinition groupDefinition = new GroupDefinition();
1328 groupDefinition.setType(groupType);
1330 //find next valid counter
1331 int nextCounter = 0;
1332 if (!isFirstGroup) {
1333 nextCounter = getNewGroupCounter(component);
1335 String name = TopologyTemplateOperation.buildSubComponentName(component.getName(), groupType, nextCounter);
1336 groupDefinition.setName(name);
1338 //Add default type properties
1339 List<PropertyDefinition> groupTypeProperties = groupTypeDefinition.getProperties();
1340 List<GroupProperty> properties = groupTypeProperties.stream()
1341 .map(GroupProperty::new)
1343 groupDefinition.convertFromGroupProperties(properties);
1345 List<GroupDefinition> gdList;
1347 gdList = createGroups(component, Arrays.asList(groupDefinition))
1349 .on(this::onFailedGroupDBOperation);
1351 gdList = addGroups(component, Arrays.asList(groupDefinition))
1353 .on(this::onFailedGroupDBOperation);
1355 return gdList.get(0);
1358 graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
1362 private void validateGroupTypePerComponent(String groupType, Component component) {
1363 String specificType = component.getComponentMetadataDefinition().getMetadataDataDefinition().getActualComponentType();
1364 if (!component.isTopologyTemplate()) {
1365 throw new ComponentException(ActionStatus.GROUP_TYPE_ILLEGAL_PER_COMPONENT, groupType,
1368 Map<String, Set<String>> excludedGroupTypesMap = ConfigurationManager.getConfigurationManager().getConfiguration()
1369 .getExcludedGroupTypesMapping();
1371 if (MapUtils.isNotEmpty(excludedGroupTypesMap) && StringUtils.isNotEmpty(specificType)) {
1372 Set<String> excludedGroupTypesPerComponent = excludedGroupTypesMap.get(specificType);
1373 if (excludedGroupTypesPerComponent!=null && excludedGroupTypesPerComponent.contains(groupType)) {
1374 throw new ComponentException(ActionStatus.GROUP_TYPE_ILLEGAL_PER_COMPONENT, groupType, specificType);
1379 private int getNewGroupCounter(Component component) {
1380 List<String> existingNames = component.getGroups()
1382 .map(GroupDataDefinition::getName)
1384 List<String> existingIds = component.getGroups()
1386 .map(GroupDataDefinition::getUniqueId)
1388 existingIds.addAll(existingNames);
1390 return Utils.getNextCounter(existingIds);
1393 public GroupDefinition updateGroup(ComponentTypeEnum componentTypeEnum, String componentId, String groupId,
1394 String userId, GroupDefinition updatedGroup) {
1396 Component component = accessValidations.validateUserCanWorkOnComponentAndLockIt(componentTypeEnum, componentId, userId, UPDATE_GROUP);
1398 GroupDefinition existingGroup = findGroupOnComponent(component, groupId)
1400 .on(se -> onGroupNotFoundInComponentError(component, groupId));
1402 String existingGroupName = existingGroup.getName();
1403 String updatedGroupName = updatedGroup.getName();
1404 assertNewNameIsValidAndUnique(existingGroupName, updatedGroupName, component);
1405 existingGroup.setName(updatedGroupName);
1407 return updateGroup(component, existingGroup, existingGroupName)
1409 .on(this::onFailedUpdateGroupDBOperation);
1412 graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
1417 private void assertNewNameIsValidAndUnique(String currentGroupName, String updatedGroupName, Component component) {
1418 if (!ValidationUtils.validateResourceInstanceNameLength(updatedGroupName)) {
1419 throw new ComponentException(ActionStatus.EXCEEDS_LIMIT, "Group Name", ValidationUtils.RSI_NAME_MAX_LENGTH.toString());
1421 if (!ValidationUtils.validateResourceInstanceName(updatedGroupName)) {
1422 throw new ComponentException(ActionStatus.INVALID_VF_MODULE_NAME, updatedGroupName);
1424 if (!ComponentValidations.validateNameIsUniqueInComponent(currentGroupName, updatedGroupName, component)) {
1425 throw new ComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, "Group", updatedGroupName);
1429 public GroupDefinition deleteGroup(ComponentTypeEnum componentTypeEnum, String componentId, String groupId,
1432 Component component = accessValidations.validateUserCanWorkOnComponentAndLockIt(componentTypeEnum, componentId, userId, DELETE_GROUP);
1434 GroupDefinition groupDefinition = findGroupOnComponent(component, groupId)
1436 .on(se -> onGroupNotFoundInComponentError(component, groupId));
1438 List<GroupDefinition> gdList = deleteGroups(component, java.util.Arrays.asList(groupDefinition))
1440 .on(this::onFailedGroupDBOperation);
1441 return gdList.get(0);
1444 graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
1448 private List<GroupDefinition> onFailedGroupDBOperation(ResponseFormat responseFormat) {
1449 titanDao.rollback();
1450 throw new ComponentException(responseFormat);
1453 private GroupDefinition onFailedUpdateGroupDBOperation(ResponseFormat responseFormat) {
1454 titanDao.rollback();
1455 throw new ComponentException(responseFormat);
1458 private GroupDefinition onGroupNotFoundInComponentError(Component component, String groupId) {
1459 throw new ComponentException(ActionStatus.GROUP_IS_MISSING, groupId,
1460 component.getSystemName(), getComponentTypeForResponse(component));
1463 private GroupTypeDefinition onGroupTypeNotFound(Component component) {
1464 throw new ComponentException(ActionStatus.GROUP_TYPE_IS_INVALID, component.getSystemName(),
1465 component.getComponentType().toString());
1468 private Boolean onFailedToLockComponent(ResponseFormat responseFormat) {
1469 throw new ComponentException(responseFormat);
1473 public Either<List<GroupDefinition>, ResponseFormat> createGroups(Component component, final List<GroupDefinition> groupDefinitions) {
1475 Map<String, GroupDataDefinition> groups = new HashMap<>();
1476 Either<List<GroupDefinition>, ResponseFormat> result = null;
1477 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1478 Either<Map<String, DataTypeDefinition>, TitanOperationStatus> allDataTypes = dataTypeCache.getAll();
1479 if (allDataTypes.isRight()) {
1480 TitanOperationStatus status = allDataTypes.right().value();
1481 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToGroup", "Failed to add property to group. Status is " + status, ErrorSeverity.ERROR);
1482 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status))));
1486 // handle groups and convert to tosca data
1487 if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1488 for (GroupDefinition groupDefinition : groupDefinitions) {
1489 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, groupDefinition, allDataTypes.left().value());
1490 if (handleGroupRes.isRight()) {
1491 result = Either.right(handleGroupRes.right().value());
1494 GroupDefinition handledGroup = handleGroupRes.left().value();
1495 groups.put(handledGroup.getName(), new GroupDataDefinition(handledGroup));
1499 if (result == null) {
1500 createGroupsResult = groupsOperation.createGroups(component, groups);
1501 if (createGroupsResult.isRight()) {
1502 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1505 if (result == null) {
1506 result = Either.left(createGroupsResult.left().value());
1511 public Either<List<GroupDefinition>, ResponseFormat> addGroups(Component component, final List<GroupDefinition> groupDefinitions) {
1513 Either<List<GroupDefinition>, ResponseFormat> result = null;
1514 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1515 List<GroupDataDefinition> groups = new ArrayList<>();
1517 Either<Map<String, DataTypeDefinition>, TitanOperationStatus> allDataTypes = dataTypeCache.getAll();
1518 if (allDataTypes.isRight()) {
1519 TitanOperationStatus status = allDataTypes.right().value();
1520 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToGroup", "Failed to add property to group. Status is " + status, ErrorSeverity.ERROR);
1521 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status))));
1525 // handle groups and convert to tosca data
1526 if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1527 for (GroupDefinition groupDefinition : groupDefinitions) {
1528 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, groupDefinition, allDataTypes.left().value());
1529 if (handleGroupRes.isRight()) {
1530 result = Either.right(handleGroupRes.right().value());
1533 GroupDefinition handledGroup = handleGroupRes.left().value();
1534 groups.add(new GroupDataDefinition(handledGroup));
1537 if (result == null) {
1538 createGroupsResult = groupsOperation.addGroups(component, groups);
1539 if (createGroupsResult.isRight()) {
1540 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1543 if (result == null) {
1544 result = Either.left(createGroupsResult.left().value());
1549 public Either<List<GroupDefinition>, ResponseFormat> deleteGroups(Component component, List<GroupDefinition> groupDefinitions) {
1551 Either<List<GroupDefinition>, StorageOperationStatus> deleteGroupsResult;
1553 deleteGroupsResult = groupsOperation.deleteGroups(component, groupDefinitions.stream().map(x -> new GroupDataDefinition(x)).collect(toList()));
1554 if (deleteGroupsResult.isRight()) {
1555 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteGroupsResult.right().value())));
1557 return Either.left(deleteGroupsResult.left().value());
1561 * Update specific group version
1564 public Either<List<GroupDefinition>, ResponseFormat> updateGroups(Component component, List<GroupDefinition> groupDefinitions) {
1566 Either<List<GroupDefinition>, ResponseFormat> result = null;
1567 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult;
1569 createGroupsResult = groupsOperation.updateGroups(component, groupDefinitions.stream().map(GroupDataDefinition::new).collect(toList()));
1570 if (createGroupsResult.isRight()) {
1571 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1574 if (result == null) {
1575 result = Either.left(createGroupsResult.left().value());
1580 public Either<GroupDefinition, ResponseFormat> handleGroup(Component component, GroupDefinition groupDefinition, Map<String, DataTypeDefinition> allDAtaTypes) {
1582 log.trace("Going to create group {}", groupDefinition);
1583 // 3. verify group not already exist
1584 String groupDefinitionName = groupDefinition.getName();
1585 if (groupExistsInComponent(groupDefinitionName, component)) {
1586 String componentTypeForResponse = getComponentTypeForResponse(component);
1587 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ALREADY_EXIST, groupDefinitionName, component.getNormalizedName(), componentTypeForResponse));
1589 // 4. verify type of group exist
1590 String groupType = groupDefinition.getType();
1591 if (StringUtils.isEmpty(groupType)) {
1592 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupDefinitionName));
1594 Either<GroupTypeDefinition, StorageOperationStatus> getGroupType = groupTypeOperation.getLatestGroupTypeByType(groupType, true);
1595 if (getGroupType.isRight()) {
1596 StorageOperationStatus status = getGroupType.right().value();
1597 if (status == StorageOperationStatus.NOT_FOUND) {
1598 BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "group type " + groupType + " cannot be found", ErrorSeverity.INFO);
1599 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, groupType));
1601 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1604 // 6. verify the component instances type are allowed according to
1605 // the member types in the group type
1606 GroupTypeDefinition groupTypeDefinition = getGroupType.left().value();
1608 Either<Boolean, ResponseFormat> areValidMembers = verifyComponentInstancesAreValidMembers(component, groupDefinitionName, groupDefinition.getMembers(), groupTypeDefinition.getMembers());
1610 if (areValidMembers.isRight()) {
1611 ResponseFormat responseFormat = areValidMembers.right().value();
1612 return Either.right(responseFormat);
1614 // 7. verify the artifacts belongs to the component
1615 Either<Boolean, ResponseFormat> areValidArtifacts = verifyArtifactsBelongsToComponent(component, groupDefinition.getArtifacts(), CREATE_GROUP);
1616 if (areValidArtifacts.isRight()) {
1617 ResponseFormat responseFormat = areValidArtifacts.right().value();
1618 return Either.right(responseFormat);
1620 List<PropertyDefinition> groupTypeProperties = groupTypeDefinition.getProperties();
1622 List<GroupProperty> properties = groupDefinition.convertToGroupProperties();
1623 List<GroupProperty> updatedGroupTypeProperties = new ArrayList<>();
1624 if (CollectionUtils.isNotEmpty(properties)) {
1625 if (CollectionUtils.isEmpty(groupTypeProperties)) {
1626 BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "group type does not have properties", ErrorSeverity.INFO);
1627 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.MATCH_NOT_FOUND))));
1630 Map<String, PropertyDefinition> groupTypePropertiesMap = groupTypeProperties.stream().collect(Collectors.toMap(p -> p.getName(), p -> p));
1632 Either<GroupProperty, TitanOperationStatus> addPropertyResult;
1634 for (GroupProperty prop : properties) {
1635 addPropertyResult = handleProperty(prop, groupTypePropertiesMap.get(prop.getName()), i, allDAtaTypes, groupType);
1636 if (addPropertyResult.isRight()) {
1637 BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "failed to validate property", ErrorSeverity.INFO);
1638 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(addPropertyResult.right().value()))));
1640 updatedGroupTypeProperties.add(addPropertyResult.left().value());
1645 if (groupDefinition.getUniqueId() == null) {
1646 String uid = UniqueIdBuilder.buildGroupingUid(component.getUniqueId(), groupDefinitionName);
1647 groupDefinition.setUniqueId(uid);
1649 groupDefinition.convertFromGroupProperties(updatedGroupTypeProperties);
1650 groupDefinition.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID());
1651 groupDefinition.setGroupUUID(UniqueIdBuilder.generateUUID());
1652 groupDefinition.setVersion(INITIAL_VERSION);
1653 groupDefinition.setTypeUid(groupTypeDefinition.getUniqueId());
1655 return Either.left(groupDefinition);
1658 private static boolean groupExistsInComponent(String groupDefinitionName, Component component) {
1659 boolean found = false;
1660 List<GroupDefinition> groups = component.getGroups();
1661 if (CollectionUtils.isNotEmpty(groups)) {
1662 found = groups.stream().filter(p -> p.getName().equalsIgnoreCase(groupDefinitionName)).findFirst().orElse(null) != null;
1667 private Either<GroupProperty, TitanOperationStatus> handleProperty(GroupProperty groupProperty, PropertyDefinition prop, Integer index, Map<String, DataTypeDefinition> allDataTypes, String groupType) {
1670 return Either.right(TitanOperationStatus.ILLEGAL_ARGUMENT);
1673 PropertyDataDefinition propDataDef = prop;
1674 String propertyType = propDataDef.getType();
1675 String value = groupProperty.getValue();
1677 Either<String, TitanOperationStatus> checkInnerType = propertyOperation.checkInnerType(propDataDef);
1678 if (checkInnerType.isRight()) {
1679 TitanOperationStatus status = checkInnerType.right().value();
1680 return Either.right(status);
1683 String innerType = checkInnerType.left().value();
1685 log.debug("Before validateAndUpdatePropertyValue");
1686 Either<Object, Boolean> isValid = propertyOperation.validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes);
1687 log.debug("After validateAndUpdatePropertyValue. isValid = {}", isValid);
1689 String newValue = value;
1690 if (isValid.isRight()) {
1691 Boolean res = isValid.right().value();
1693 return Either.right(TitanOperationStatus.ILLEGAL_ARGUMENT);
1696 Object object = isValid.left().value();
1697 if (object != null) {
1698 newValue = object.toString();
1702 String uniqueId = shouldReconstructUniqueId(groupType) ? UniqueIdBuilder.buildGroupPropertyValueUid(prop.getUniqueId(), index)
1703 : prop.getUniqueId();
1705 groupProperty.setUniqueId(uniqueId);
1706 groupProperty.setValue(newValue);
1707 groupProperty.setType(prop.getType());
1708 groupProperty.setDefaultValue(prop.getDefaultValue());
1709 groupProperty.setDescription(prop.getDescription());
1710 groupProperty.setSchema(prop.getSchema());
1711 groupProperty.setPassword(prop.isPassword());
1712 groupProperty.setParentUniqueId(prop.getUniqueId());
1714 log.debug("Before adding property value to graph {}", groupProperty);
1716 return Either.left(groupProperty);
1719 // For old groups we want to leave indexing of property
1720 // For new groups we just need the types
1721 private boolean shouldReconstructUniqueId(String groupType) {
1722 return Constants.GROUP_TOSCA_HEAT.equals(groupType) || Constants.DEFAULT_GROUP_VF_MODULE.equals(groupType);