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 org.apache.commons.collections.CollectionUtils;
25 import org.apache.commons.collections.MapUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.lang3.math.NumberUtils;
28 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
29 import org.openecomp.sdc.be.components.impl.lock.LockingTransactional;
30 import org.openecomp.sdc.be.components.validation.AccessValidations;
31 import org.openecomp.sdc.be.components.validation.ComponentValidations;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
34 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
35 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
36 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
37 import org.openecomp.sdc.be.model.Component;
38 import org.openecomp.sdc.be.model.ComponentInstance;
39 import org.openecomp.sdc.be.model.GroupDefinition;
40 import org.openecomp.sdc.be.model.GroupProperty;
41 import org.openecomp.sdc.be.model.PropertyDefinition;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
43 import org.openecomp.sdc.be.model.operations.StorageException;
44 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
45 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
46 import org.openecomp.sdc.common.util.ValidationUtils;
47 import org.springframework.transaction.annotation.Transactional;
49 import java.util.ArrayList;
50 import java.util.EnumMap;
51 import java.util.HashMap;
52 import java.util.List;
54 import java.util.stream.Collectors;
56 import static org.openecomp.sdc.be.components.impl.BaseBusinessLogic.enumHasValueFilter;
58 @org.springframework.stereotype.Component
59 public class GroupBusinessLogicNew {
61 private final AccessValidations accessValidations;
62 private final ComponentValidations componentValidations;
63 private final GroupsOperation groupsOperation;
64 private final GroupOperation groupOperation;
66 public GroupBusinessLogicNew(AccessValidations accessValidations, ComponentValidations componentValidations, GroupsOperation groupsOperation, GroupOperation groupOperation) {
67 this.accessValidations = accessValidations;
68 this.componentValidations = componentValidations;
69 this.groupsOperation = groupsOperation;
70 this.groupOperation = groupOperation;
74 public List<String> updateMembers(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId, List<String> members) {
75 Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP MEMBERS");
76 GroupDefinition groupDefinition = getGroup(component, groupUniqueId);
77 groupDefinition.setMembers(buildMembersMap(component, members));
78 groupsOperation.updateGroupOnComponent(componentId, groupDefinition, PromoteVersionEnum.MINOR);
79 return new ArrayList<>(groupDefinition.getMembers().values());
83 public List<GroupProperty> updateProperties(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId, List<GroupProperty> newProperties) {
84 Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP PROPERTIES");
85 GroupDefinition currentGroup = getGroup(component, groupUniqueId);
86 validateUpdatedPropertiesAndSetEmptyValues(currentGroup, newProperties);
87 return groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, newProperties, PromoteVersionEnum.MINOR)
89 .on(this::onUpdatePropertyError);
93 public List<PropertyDataDefinition> getProperties(String componentType, String userId, String componentId, String groupUniqueId) {
94 Component component = accessValidations.validateUserCanRetrieveComponentData(componentId, componentType, userId, "GET GROUP PROPERTIES");
95 GroupDefinition currentGroup = getGroup(component, groupUniqueId);
96 return currentGroup.getProperties();
99 private List<GroupProperty> onUpdatePropertyError(StorageOperationStatus storageOperationStatus) {
100 throw new StorageException(storageOperationStatus);
103 private Map<String, String> buildMembersMap(Component component, List<String> newMemberUniqueIds) {
104 Map<String, String> nameToUniqueId = new HashMap<>();
105 for (String memberUniqueId : newMemberUniqueIds) {
106 ComponentInstance componentInstance = getComponentInstance(component, memberUniqueId);
107 nameToUniqueId.put(componentInstance.getName(), componentInstance.getUniqueId());
109 return nameToUniqueId;
112 private ComponentInstance getComponentInstance(Component component, String memberUniqueId) {
113 return componentValidations.getComponentInstance(component, memberUniqueId)
114 .orElseThrow(() -> new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
116 component.getActualComponentType(), component.getSystemName()));
119 private GroupDefinition getGroup(Component component, String groupUniqueId) {
120 return component.getGroupById(groupUniqueId)
121 .orElseThrow(() -> new ByActionStatusComponentException(ActionStatus.GROUP_IS_MISSING,
122 component.getSystemName(), component.getActualComponentType()));
125 private void validateUpdatedPropertiesAndSetEmptyValues(GroupDefinition originalGroup, List<GroupProperty> groupPropertiesToUpdate) {
127 if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) {
128 throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY);
130 if (CollectionUtils.isEmpty(originalGroup.getProperties())) {
131 throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, groupPropertiesToUpdate.get(NumberUtils.INTEGER_ZERO).getName());
133 Map<String, GroupProperty> originalProperties = originalGroup.convertToGroupProperties()
135 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
138 for (GroupProperty gp : groupPropertiesToUpdate) {
139 String updatedPropertyName = gp.getName();
140 if (!originalProperties.containsKey(updatedPropertyName)) {
141 throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, updatedPropertyName);
143 if (!isOnlyGroupPropertyValueChanged(gp, originalProperties.get(updatedPropertyName))) {
144 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY, updatedPropertyName);
146 if (StringUtils.isEmpty(gp.getValue())) {
147 gp.setValue(originalProperties.get(updatedPropertyName).getDefaultValue());
149 StorageOperationStatus sos = groupOperation.validateAndUpdatePropertyValue(gp);
150 if (StorageOperationStatus.OK != sos) {
151 throw new StorageException(sos, updatedPropertyName);
155 validatePropertyBusinessLogic(groupPropertiesToUpdate, originalGroup);
158 private void validatePropertyBusinessLogic(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
160 Map<PropertyDefinition.PropertyNames, String> enumValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
161 for (GroupProperty gp : groupPropertiesToUpdate) {
162 // Filter out non special properties which does not have Enum
163 final PropertyDefinition.PropertyNames gpEnum = PropertyDefinition.PropertyNames.findName(gp.getName());
164 if (gpEnum != null) {
165 enumValueMap.put(gpEnum, gp.getValue());
168 if (MapUtils.isEmpty(enumValueMap)) {
172 validateVFInstancesLogic(enumValueMap, prepareMapWithOriginalProperties(originalGroup));
174 if (enumValueMap.containsKey(PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION) || enumValueMap.containsKey(PropertyDefinition.PropertyNames.VF_MODULE_LABEL)) {
175 groupPropertiesToUpdate.stream()
176 .filter(e -> enumHasValueFilter(e.getName(), PropertyDefinition.PropertyNames::findName, PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION, PropertyDefinition.PropertyNames.VF_MODULE_LABEL))
177 .forEach(this::validateFreeText);
181 private Map<PropertyDefinition.PropertyNames, String> prepareMapWithOriginalProperties(GroupDefinition originalGroup) {
182 Map<PropertyDefinition.PropertyNames, String> oldValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
183 PropertyDefinition.PropertyNames[] propertiesToCheck = new PropertyDefinition.PropertyNames[] { PropertyDefinition.PropertyNames.INITIAL_COUNT, PropertyDefinition.PropertyNames.MAX_INSTANCES, PropertyDefinition.PropertyNames.MIN_INSTANCES };
185 for (GroupProperty gp : originalGroup.convertToGroupProperties()) {
186 if (enumHasValueFilter(gp.getName(), PropertyDefinition.PropertyNames::findName, propertiesToCheck)) {
187 oldValueMap.put(PropertyDefinition.PropertyNames.findName(gp.getName()), gp.getValue());
190 if (StringUtils.isEmpty(oldValueMap.get(PropertyDefinition.PropertyNames.MAX_INSTANCES))) {
191 oldValueMap.put(PropertyDefinition.PropertyNames.MAX_INSTANCES, String.valueOf(Integer.MAX_VALUE));
196 private void validateVFInstancesLogic(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues) {
197 if (!newValues.containsKey(PropertyDefinition.PropertyNames.INITIAL_COUNT)
198 && !newValues.containsKey(PropertyDefinition.PropertyNames.MAX_INSTANCES)
199 && !newValues.containsKey(PropertyDefinition.PropertyNames.MIN_INSTANCES)) {
202 int latestMaxInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES);
203 int latestInitialCount = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT);
204 int latestMinInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES);
206 if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT)
207 && (latestInitialCount > latestMaxInstances || latestInitialCount < latestMinInstances)) {
208 throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE, PropertyDefinition.PropertyNames.INITIAL_COUNT.getPropertyName(), String.valueOf(latestMinInstances), String.valueOf(latestMaxInstances));
210 if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES) &&
211 latestMaxInstances < latestInitialCount) {
212 throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyDefinition.PropertyNames.MAX_INSTANCES.getPropertyName(), "higher", String.valueOf(latestInitialCount));
214 if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES) &&
215 latestMinInstances > latestInitialCount) {
216 throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyDefinition.PropertyNames.MIN_INSTANCES.getPropertyName(), "lower", String.valueOf(latestInitialCount));
220 private boolean isPropertyChanged(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues, final PropertyDefinition.PropertyNames minInstances) {
221 return newValues.containsKey(minInstances) && !newValues.get(minInstances).equals(parentValues.get(minInstances));
224 private int getLatestIntProperty(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues, PropertyDefinition.PropertyNames propertyKey) {
226 if (newValues.containsKey(propertyKey)) {
227 value = newValues.get(propertyKey);
229 value = parentValues.get(propertyKey);
231 return Integer.valueOf(value);
234 private boolean isOnlyGroupPropertyValueChanged(GroupProperty groupProperty1, GroupProperty groupProperty2) {
235 GroupProperty groupProperty1Duplicate = new GroupProperty(groupProperty1);
236 groupProperty1Duplicate.setValue(null);
237 groupProperty1Duplicate.setSchema(null);
238 groupProperty1Duplicate.setParentUniqueId(null);
239 GroupProperty groupProperty2Duplicate = new GroupProperty(groupProperty2);
240 groupProperty2Duplicate.setValue(null);
241 groupProperty2Duplicate.setSchema(null);
242 groupProperty2Duplicate.setParentUniqueId(null);
243 return StringUtils.equals(groupProperty1Duplicate.getValueUniqueUid(), groupProperty2Duplicate.getValueUniqueUid())
244 && groupProperty1Duplicate.equals(groupProperty2Duplicate);
247 private void validateFreeText(GroupProperty groupPropertyToUpdate) {
248 final String groupTypeValue = groupPropertyToUpdate.getValue();
249 if (!org.apache.commons.lang3.StringUtils.isEmpty(groupTypeValue)) {
250 if (!ValidationUtils.validateDescriptionLength(groupTypeValue)) {
251 throw new ByActionStatusComponentException(ActionStatus.COMPONENT_DESCRIPTION_EXCEEDS_LIMIT,
252 NodeTypeEnum.Property.getName(),
253 String.valueOf(ValidationUtils.COMPONENT_DESCRIPTION_MAX_LENGTH));
254 } else if (!ValidationUtils.validateIsEnglish(groupTypeValue)) {
255 throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INVALID_DESCRIPTION,
256 NodeTypeEnum.Property.getName());