re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / GroupBusinessLogicNew.java
1 package org.openecomp.sdc.be.components.impl;
2
3 import org.apache.commons.collections.CollectionUtils;
4 import org.apache.commons.collections.MapUtils;
5 import org.apache.commons.lang.StringUtils;
6 import org.apache.commons.lang3.math.NumberUtils;
7 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
8 import org.openecomp.sdc.be.components.impl.lock.LockingTransactional;
9 import org.openecomp.sdc.be.components.validation.AccessValidations;
10 import org.openecomp.sdc.be.components.validation.ComponentValidations;
11 import org.openecomp.sdc.be.dao.api.ActionStatus;
12 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
13 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
14 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
15 import org.openecomp.sdc.be.model.*;
16 import org.openecomp.sdc.be.model.jsontitan.operations.GroupsOperation;
17 import org.openecomp.sdc.be.model.operations.StorageException;
18 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
19 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
20 import org.openecomp.sdc.common.util.ValidationUtils;
21 import org.springframework.transaction.annotation.Transactional;
22
23 import java.util.*;
24 import java.util.stream.Collectors;
25
26 import static org.openecomp.sdc.be.components.impl.BaseBusinessLogic.enumHasValueFilter;
27
28 @org.springframework.stereotype.Component
29 public class GroupBusinessLogicNew {
30
31     private final AccessValidations accessValidations;
32     private final ComponentValidations componentValidations;
33     private final GroupsOperation groupsOperation;
34     private final GroupOperation groupOperation;
35
36     public GroupBusinessLogicNew(AccessValidations accessValidations, ComponentValidations componentValidations, GroupsOperation groupsOperation, GroupOperation groupOperation) {
37         this.accessValidations = accessValidations;
38         this.componentValidations = componentValidations;
39         this.groupsOperation = groupsOperation;
40         this.groupOperation = groupOperation;
41     }
42
43     @LockingTransactional
44     public List<String> updateMembers(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId, List<String> members) {
45         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP MEMBERS");
46         GroupDefinition groupDefinition = getGroup(component, groupUniqueId);
47         groupDefinition.setMembers(buildMembersMap(component, members));
48         groupsOperation.updateGroupOnComponent(componentId, groupDefinition);
49         return new ArrayList<>(groupDefinition.getMembers().values());
50     }
51
52     @LockingTransactional
53     public List<GroupProperty> updateProperties(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId, List<GroupProperty> newProperties) {
54         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP PROPERTIES");
55         GroupDefinition currentGroup = getGroup(component, groupUniqueId);
56         validateUpdatedPropertiesAndSetEmptyValues(currentGroup, newProperties);
57         return groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, newProperties)
58                 .left()
59                 .on(this::onUpdatePropertyError);
60     }
61
62     @Transactional
63     public List<PropertyDataDefinition> getProperties(String componentType, String userId, String componentId, String groupUniqueId) {
64         Component component = accessValidations.validateUserCanRetrieveComponentData(componentId, componentType, userId, "GET GROUP PROPERTIES");
65         GroupDefinition currentGroup = getGroup(component, groupUniqueId);
66         return currentGroup.getProperties();
67     }
68
69     private List<GroupProperty> onUpdatePropertyError(StorageOperationStatus storageOperationStatus) {
70         throw new StorageException(storageOperationStatus);
71     }
72
73     private Map<String, String> buildMembersMap(Component component, List<String> newMemberUniqueIds) {
74         Map<String, String> nameToUniqueId = new HashMap<>();
75         for (String memberUniqueId : newMemberUniqueIds) {
76             ComponentInstance componentInstance = getComponentInstance(component, memberUniqueId);
77             nameToUniqueId.put(componentInstance.getName(), componentInstance.getUniqueId());
78         }
79         return nameToUniqueId;
80     }
81
82     private ComponentInstance getComponentInstance(Component component, String memberUniqueId) {
83         return componentValidations.getComponentInstance(component, memberUniqueId)
84                 .orElseThrow(() -> new ComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER,
85                         memberUniqueId, "",
86                         component.getActualComponentType(), component.getSystemName()));
87     }
88
89     private GroupDefinition getGroup(Component component, String groupUniqueId) {
90         return component.getGroupById(groupUniqueId)
91                 .orElseThrow(() -> new ComponentException(ActionStatus.GROUP_IS_MISSING,
92                         component.getSystemName(), component.getActualComponentType()));
93     }
94
95     private void validateUpdatedPropertiesAndSetEmptyValues(GroupDefinition originalGroup, List<GroupProperty> groupPropertiesToUpdate) {
96
97         if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) {
98             throw new ComponentException(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY);
99         }
100         if (CollectionUtils.isEmpty(originalGroup.getProperties())) {
101             throw new ComponentException(ActionStatus.PROPERTY_NOT_FOUND, groupPropertiesToUpdate.get(NumberUtils.INTEGER_ZERO).getName());
102         }
103         Map<String, GroupProperty> originalProperties = originalGroup.convertToGroupProperties()
104                 .stream()
105                 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
106
107
108         for (GroupProperty gp : groupPropertiesToUpdate) {
109             String updatedPropertyName = gp.getName();
110             if (!originalProperties.containsKey(updatedPropertyName)) {
111                 throw new ComponentException(ActionStatus.PROPERTY_NOT_FOUND, updatedPropertyName);
112             }
113             if (!isOnlyGroupPropertyValueChanged(gp, originalProperties.get(updatedPropertyName))) {
114                 throw new ComponentException(ActionStatus.INVALID_PROPERTY, updatedPropertyName);
115             }
116             if (StringUtils.isEmpty(gp.getValue())) {
117                 gp.setValue(originalProperties.get(updatedPropertyName).getDefaultValue());
118             }
119             StorageOperationStatus sos = groupOperation.validateAndUpdatePropertyValue(gp);
120             if (StorageOperationStatus.OK != sos) {
121                 throw new StorageException(sos, updatedPropertyName);
122             }
123         }
124
125         validatePropertyBusinessLogic(groupPropertiesToUpdate, originalGroup);
126     }
127
128     private void validatePropertyBusinessLogic(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
129
130         Map<PropertyDefinition.PropertyNames, String> enumValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
131         for (GroupProperty gp : groupPropertiesToUpdate) {
132             // Filter out non special properties which does not have Enum
133             final PropertyDefinition.PropertyNames gpEnum = PropertyDefinition.PropertyNames.findName(gp.getName());
134             if (gpEnum != null) {
135                 enumValueMap.put(gpEnum, gp.getValue());
136             }
137         }
138         if (MapUtils.isEmpty(enumValueMap)) {
139             return;
140         }
141
142         validateVFInstancesLogic(enumValueMap, prepareMapWithOriginalProperties(originalGroup));
143
144         if (enumValueMap.containsKey(PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION) || enumValueMap.containsKey(PropertyDefinition.PropertyNames.VF_MODULE_LABEL)) {
145             groupPropertiesToUpdate.stream()
146                     .filter(e -> enumHasValueFilter(e.getName(), PropertyDefinition.PropertyNames::findName, PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION, PropertyDefinition.PropertyNames.VF_MODULE_LABEL))
147                     .forEach(this::validateFreeText);
148         }
149     }
150
151     private Map<PropertyDefinition.PropertyNames, String> prepareMapWithOriginalProperties(GroupDefinition originalGroup) {
152         Map<PropertyDefinition.PropertyNames, String> oldValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
153         PropertyDefinition.PropertyNames[] propertiesToCheck = new PropertyDefinition.PropertyNames[] { PropertyDefinition.PropertyNames.INITIAL_COUNT, PropertyDefinition.PropertyNames.MAX_INSTANCES, PropertyDefinition.PropertyNames.MIN_INSTANCES };
154
155         for (GroupProperty gp : originalGroup.convertToGroupProperties()) {
156             if (enumHasValueFilter(gp.getName(), PropertyDefinition.PropertyNames::findName, propertiesToCheck)) {
157                 oldValueMap.put(PropertyDefinition.PropertyNames.findName(gp.getName()), gp.getValue());
158             }
159         }
160         if (StringUtils.isEmpty(oldValueMap.get(PropertyDefinition.PropertyNames.MAX_INSTANCES))) {
161             oldValueMap.put(PropertyDefinition.PropertyNames.MAX_INSTANCES, String.valueOf(Integer.MAX_VALUE));
162         }
163         return oldValueMap;
164     }
165
166     private void validateVFInstancesLogic(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues) {
167         if (!newValues.containsKey(PropertyDefinition.PropertyNames.INITIAL_COUNT)
168                 && !newValues.containsKey(PropertyDefinition.PropertyNames.MAX_INSTANCES)
169                 && !newValues.containsKey(PropertyDefinition.PropertyNames.MIN_INSTANCES)) {
170             return;
171         }
172         int latestMaxInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES);
173         int latestInitialCount = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT);
174         int latestMinInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES);
175
176         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT)
177                 && (latestInitialCount > latestMaxInstances || latestInitialCount < latestMinInstances)) {
178             throw new ComponentException(ActionStatus.INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE, PropertyDefinition.PropertyNames.INITIAL_COUNT.getPropertyName(), String.valueOf(latestMinInstances), String.valueOf(latestMaxInstances));
179         }
180         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES) &&
181                 latestMaxInstances < latestInitialCount) {
182             throw new ComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyDefinition.PropertyNames.MAX_INSTANCES.getPropertyName(), "higher", String.valueOf(latestInitialCount));
183         }
184         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES) &&
185                 latestMinInstances > latestInitialCount) {
186             throw new ComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyDefinition.PropertyNames.MIN_INSTANCES.getPropertyName(), "lower", String.valueOf(latestInitialCount));
187         }
188     }
189
190     private boolean isPropertyChanged(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues, final PropertyDefinition.PropertyNames minInstances) {
191         return newValues.containsKey(minInstances) && !newValues.get(minInstances).equals(parentValues.get(minInstances));
192     }
193
194     private int getLatestIntProperty(Map<PropertyDefinition.PropertyNames, String> newValues, Map<PropertyDefinition.PropertyNames, String> parentValues, PropertyDefinition.PropertyNames propertyKey) {
195         String value;
196         if (newValues.containsKey(propertyKey)) {
197             value = newValues.get(propertyKey);
198         } else {
199             value = parentValues.get(propertyKey);
200         }
201         return Integer.valueOf(value);
202     }
203
204     private boolean isOnlyGroupPropertyValueChanged(GroupProperty groupProperty1, GroupProperty groupProperty2) {
205         GroupProperty groupProperty1Duplicate = new GroupProperty(groupProperty1);
206         groupProperty1Duplicate.setValue(null);
207         groupProperty1Duplicate.setSchema(null);
208         groupProperty1Duplicate.setParentUniqueId(null);
209         GroupProperty groupProperty2Duplicate = new GroupProperty(groupProperty2);
210         groupProperty2Duplicate.setValue(null);
211         groupProperty2Duplicate.setSchema(null);
212         groupProperty2Duplicate.setParentUniqueId(null);
213         return StringUtils.equals(groupProperty1Duplicate.getValueUniqueUid(), groupProperty2Duplicate.getValueUniqueUid())
214                 && groupProperty1Duplicate.equals(groupProperty2Duplicate);
215     }
216
217     private void validateFreeText(GroupProperty groupPropertyToUpdate) {
218         final String groupTypeValue = groupPropertyToUpdate.getValue();
219         if (!org.apache.commons.lang3.StringUtils.isEmpty(groupTypeValue)) {
220             if (!ValidationUtils.validateDescriptionLength(groupTypeValue)) {
221                 throw new ComponentException(ActionStatus.COMPONENT_DESCRIPTION_EXCEEDS_LIMIT,
222                         NodeTypeEnum.Property.getName(),
223                         String.valueOf(ValidationUtils.COMPONENT_DESCRIPTION_MAX_LENGTH));
224             } else if (!ValidationUtils.validateIsEnglish(groupTypeValue)) {
225                 throw new ComponentException(ActionStatus.COMPONENT_INVALID_DESCRIPTION,
226                         NodeTypeEnum.Property.getName());
227             }
228         }
229     }
230
231 }