Centralize TOSCA function validation
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / GroupBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.impl;
23
24 import static java.util.stream.Collectors.toList;
25 import static org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter.extractCapabilitiesFromGroups;
26 import static org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter.extractCapabilityPropertiesFromGroups;
27
28 import fj.data.Either;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.EnumMap;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Optional;
39 import java.util.Set;
40 import java.util.regex.Pattern;
41 import java.util.stream.Collectors;
42 import org.apache.commons.collections.CollectionUtils;
43 import org.apache.commons.collections.MapUtils;
44 import org.apache.commons.io.FilenameUtils;
45 import org.apache.commons.lang3.StringUtils;
46 import org.apache.commons.lang3.math.NumberUtils;
47 import org.apache.commons.lang3.tuple.ImmutablePair;
48 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
49 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
50 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
51 import org.openecomp.sdc.be.components.impl.lock.LockingTransactional;
52 import org.openecomp.sdc.be.components.impl.policy.PolicyTargetsUpdateHandler;
53 import org.openecomp.sdc.be.components.utils.Utils;
54 import org.openecomp.sdc.be.components.validation.AccessValidations;
55 import org.openecomp.sdc.be.components.validation.ComponentValidations;
56 import org.openecomp.sdc.be.config.BeEcompErrorManager;
57 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
58 import org.openecomp.sdc.be.config.ConfigurationManager;
59 import org.openecomp.sdc.be.dao.api.ActionStatus;
60 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
61 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
62 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
65 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
66 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
67 import org.openecomp.sdc.be.datatypes.enums.CreatedFrom;
68 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
69 import org.openecomp.sdc.be.info.ArtifactDefinitionInfo;
70 import org.openecomp.sdc.be.info.ArtifactTemplateInfo;
71 import org.openecomp.sdc.be.info.GroupDefinitionInfo;
72 import org.openecomp.sdc.be.model.ArtifactDefinition;
73 import org.openecomp.sdc.be.model.Component;
74 import org.openecomp.sdc.be.model.ComponentInstance;
75 import org.openecomp.sdc.be.model.ComponentParametersView;
76 import org.openecomp.sdc.be.model.DataTypeDefinition;
77 import org.openecomp.sdc.be.model.GroupDefinition;
78 import org.openecomp.sdc.be.model.GroupInstance;
79 import org.openecomp.sdc.be.model.GroupInstanceProperty;
80 import org.openecomp.sdc.be.model.GroupProperty;
81 import org.openecomp.sdc.be.model.GroupTypeDefinition;
82 import org.openecomp.sdc.be.model.PropertyDefinition;
83 import org.openecomp.sdc.be.model.PropertyDefinition.GroupInstancePropertyValueUpdateBehavior;
84 import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames;
85 import org.openecomp.sdc.be.model.Resource;
86 import org.openecomp.sdc.be.model.User;
87 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
88 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
89 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
90 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.TopologyTemplateOperation;
91 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
92 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
93 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
94 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
95 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
96 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
97 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
98 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
99 import org.openecomp.sdc.common.api.Constants;
100 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
101 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
102 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
103 import org.openecomp.sdc.common.log.enums.LogLevel;
104 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
105 import org.openecomp.sdc.common.log.enums.StatusCode;
106 import org.openecomp.sdc.common.log.wrappers.Logger;
107 import org.openecomp.sdc.common.util.ValidationUtils;
108 import org.openecomp.sdc.exception.ResponseFormat;
109 import org.springframework.beans.factory.annotation.Autowired;
110
111 @org.springframework.stereotype.Component("groupBusinessLogic")
112 public class GroupBusinessLogic extends BaseBusinessLogic {
113
114     public static final String GROUP_DELIMITER_REGEX = "\\.\\.";
115     public static final String INITIAL_VERSION = "0.0";
116     private static final String ADDING_GROUP = "AddingGroup";
117     private static final String CREATE_GROUP = "CreateGroup";
118     private static final String UPDATE_GROUP = "UpdateGroup";
119     private static final String GET_GROUP = "GetGroup";
120     private static final String DELETE_GROUP = "DeleteGroup";
121     private static final Logger log = Logger.getLogger(GroupBusinessLogic.class);
122     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(GroupBusinessLogic.class.getName());
123     private final AccessValidations accessValidations;
124     private final PolicyTargetsUpdateHandler policyTargetsUpdateHandler;
125     @javax.annotation.Resource
126     private final GroupsOperation groupsOperation;
127
128     @Autowired
129     public GroupBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
130                               IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
131                               InterfaceLifecycleOperation interfaceLifecycleTypeOperation, AccessValidations accessValidations,
132                               GroupsOperation groupsOperation, PolicyTargetsUpdateHandler policyTargetsUpdateHandler,
133                               ArtifactsOperations artifactToscaOperation) {
134         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
135             artifactToscaOperation);
136         this.accessValidations = accessValidations;
137         this.groupsOperation = groupsOperation;
138         this.policyTargetsUpdateHandler = policyTargetsUpdateHandler;
139     }
140
141     private static boolean groupExistsInComponent(String groupDefinitionName, Component component) {
142         boolean found = false;
143         List<GroupDefinition> groups = component.getGroups();
144         if (CollectionUtils.isNotEmpty(groups)) {
145             found = groups.stream()
146                 .filter(p -> (p.getName().equalsIgnoreCase(groupDefinitionName)) || p.getInvariantName().equalsIgnoreCase(groupDefinitionName))
147                 .findFirst().orElse(null) != null;
148         }
149         return found;
150     }
151
152     private String getComponentTypeForResponse(org.openecomp.sdc.be.model.Component component) {
153         String componentTypeForResponse = "SERVICE";
154         if (component instanceof Resource) {
155             componentTypeForResponse = ((Resource) component).getResourceType().name();
156         }
157         return componentTypeForResponse;
158     }
159
160     /**
161      * Verify that the artifact members belongs to the component
162      *
163      * @param component
164      * @param artifacts
165      * @return
166      */
167     private Either<Boolean, ResponseFormat> verifyArtifactsBelongsToComponent(Component component, List<String> artifacts, String context) {
168         if (CollectionUtils.isEmpty(artifacts)) {
169             return Either.left(true);
170         }
171         Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
172         if (MapUtils.isEmpty(deploymentArtifacts)) {
173             BeEcompErrorManager.getInstance()
174                 .logInvalidInputError(context, "No deployment artifact found under component " + component.getNormalizedName(), ErrorSeverity.INFO);
175             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
176         }
177         List<String> currentArtifacts = deploymentArtifacts.values().stream().map(ArtifactDefinition::getUniqueId).collect(toList());
178         log.debug("The deployment artifacts of component {} are {}", component.getNormalizedName(), deploymentArtifacts);
179         if (!currentArtifacts.containsAll(artifacts)) {
180             BeEcompErrorManager.getInstance()
181                 .logInvalidInputError(context, "Not all artifacts belongs to component " + component.getNormalizedName(), ErrorSeverity.INFO);
182             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
183         }
184         return Either.left(true);
185     }
186
187     /**
188      * verify that the members are component instances of the component
189      *
190      * @param component
191      * @param groupMembers
192      * @param memberToscaTypes
193      * @return
194      */
195     private Either<Boolean, ResponseFormat> verifyComponentInstancesAreValidMembers(Component component, String groupName,
196                                                                                     Map<String, String> groupMembers, List<String> memberToscaTypes) {
197         if (MapUtils.isEmpty(groupMembers)) {
198             return Either.left(true);
199         }
200         if (CollectionUtils.isEmpty(memberToscaTypes)) {
201             return Either.left(true);
202         }
203         List<ComponentInstance> componentInstances = component.getComponentInstances();
204         if (CollectionUtils.isNotEmpty(componentInstances)) {
205             Map<String, ComponentInstance> compInstUidToCompInstMap = componentInstances.stream()
206                 .collect(Collectors.toMap(ComponentInstance::getUniqueId, p -> p));
207             Set<String> allCompInstances = compInstUidToCompInstMap.keySet();
208             for (Entry<String, String> groupMember : groupMembers.entrySet()) {
209                 String compName = groupMember.getKey();
210                 String compUid = groupMember.getValue();
211                 if (!allCompInstances.contains(compUid)) {
212                     /*
213                      * %1 - member name %2 - group name %3 - VF name %4 - component type [VF ]
214                      */
215                     String componentTypeForResponse = getComponentTypeForResponse(component);
216                     BeEcompErrorManager.getInstance()
217                         .logInvalidInputError(CREATE_GROUP, "Not all group members exists under the component", ErrorSeverity.INFO);
218                     return Either.right(componentsUtils
219                         .getResponseFormat(ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, compName, groupName, component.getNormalizedName(),
220                             componentTypeForResponse));
221                 }
222             }
223         }
224         return Either.left(true);
225     }
226
227     /**
228      * Update GroupDefinition metadata
229      *
230      * @param componentId
231      * @param user
232      * @param componentType
233      * @param updatedGroup
234      * @param inTransaction
235      * @return
236      */
237     public Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(String componentId, User user, ComponentTypeEnum componentType,
238                                                                                   GroupDefinition updatedGroup, boolean inTransaction,
239                                                                                   boolean shouldLock) {
240         Either<GroupDefinition, ResponseFormat> result = null;
241         boolean failed = false;
242         try {
243             // Validate user exist
244             validateUserExists(user.getUserId());
245             // Validate component exist
246             org.openecomp.sdc.be.model.Component component = validateComponentExists(componentId, componentType, null);
247             // validate we can work on component
248             validateCanWorkOnComponent(component, user.getUserId());
249             List<GroupDefinition> currentGroups = component.getGroups();
250             if (CollectionUtils.isEmpty(currentGroups)) {
251                 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(),
252                     component.getName(), ActionStatus.GROUP_IS_MISSING);
253                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(),
254                     component.getComponentType().getValue()));
255                 return result;
256             }
257             // Validate groups exists in the component
258             Optional<GroupDefinition> currentGroupOpt = currentGroups.stream().filter(g -> g.getUniqueId().equals(updatedGroup.getUniqueId()))
259                 .findAny();
260             if (!currentGroupOpt.isPresent()) {
261                 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(),
262                     component.getName(), ActionStatus.GROUP_IS_MISSING);
263                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(),
264                     component.getComponentType().getValue()));
265                 return result;
266             }
267             GroupDefinition currentGroup = currentGroupOpt.get();
268             if (shouldLock) {
269                 lockComponent(componentId, component, "Update GroupDefinition Metadata");
270             }
271             // Validate group type is vfModule
272             if (currentGroup.getType().equals(Constants.GROUP_TOSCA_HEAT)) {
273                 log.error("Failed to update the metadata of group {}. Group type is {} and cannot be updated", currentGroup.getName(),
274                     currentGroup.getType());
275                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, updatedGroup.getType());
276                 result = Either.right(responseFormat);
277                 return result;
278             }
279             result = updateGroupMetadata(component, currentGroup, updatedGroup);
280             return result;
281         } catch (ComponentException e) {
282             failed = true;
283             throw e;
284         } finally {
285             if (!failed) {
286                 janusGraphDao.commit();
287             } else {
288                 janusGraphDao.rollback();
289             }
290             if (shouldLock) {
291                 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
292             }
293         }
294     }
295
296     private Either<GroupDefinition, ResponseFormat> updateGroupMetadata(Component component, GroupDefinition currentGroup,
297                                                                         GroupDefinition updatedGroup) {
298         String currentGroupName = currentGroup.getName();
299         Either<GroupDefinition, ResponseFormat> result = validateAndUpdateGroupMetadata(currentGroup, updatedGroup);
300         if (result.isRight()) {
301             log.debug("Failed to validate a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
302         }
303         if (result.isLeft()) {
304             result = updateGroup(component, currentGroup, currentGroupName);
305         }
306         return result;
307     }
308
309     private Either<GroupDefinition, ResponseFormat> updateGroup(Component component, GroupDefinition updatedGroup, String currentGroupName) {
310         Either<GroupDefinition, StorageOperationStatus> handleGroupRes;
311         Either<GroupDefinition, ResponseFormat> result = null;
312         handleGroupRes = groupsOperation.updateGroup(component, updatedGroup);
313         if (handleGroupRes.isRight()) {
314             log.debug("Failed to update a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
315             result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(handleGroupRes.right().value())));
316         }
317         if (result == null) {
318             result = Either.left(updatedGroup);
319         }
320         return result;
321     }
322
323     /**
324      * Validate and update GroupDefinition metadata
325      *
326      * @param currentGroup
327      * @param groupUpdate
328      * @return
329      **/
330     private Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
331         // Check if to update, and update GroupDefinition name.
332         Either<Boolean, ResponseFormat> response = validateAndUpdateGroupName(currentGroup, groupUpdate);
333         if (response.isRight()) {
334             ResponseFormat errorResponse = response.right().value();
335             return Either.right(errorResponse);
336         }
337         // Do not allow to update GroupDefinition version directly.
338         String versionUpdated = groupUpdate.getVersion();
339         String versionCurrent = currentGroup.getVersion();
340         if (versionUpdated != null && !versionCurrent.equals(versionUpdated)) {
341             log.info("update Group: recived request to update version to {} the field is not updatable ignoring.", versionUpdated);
342         }
343         return Either.left(currentGroup);
344     }
345
346     /**
347      * Validate and update GroupDefinition name
348      *
349      * @param currentGroup
350      * @param groupUpdate
351      * @return
352      */
353     private Either<Boolean, ResponseFormat> validateAndUpdateGroupName(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
354         String nameUpdated = groupUpdate.getName();
355         String nameCurrent = currentGroup.getName();
356         if (!nameCurrent.equals(nameUpdated)) {
357             Either<Boolean, ResponseFormat> validatNameResponse = validateGroupName(currentGroup.getName(), groupUpdate.getName(), true);
358             if (validatNameResponse.isRight()) {
359                 ResponseFormat errorRespons = validatNameResponse.right().value();
360                 return Either.right(errorRespons);
361             }
362             currentGroup.setName(groupUpdate.getName());
363         }
364         return Either.left(true);
365     }
366
367     /**
368      * Validate that group name to update is valid (same as current group name except for middle part). For example: Current group name:
369      * MyResource..MyDesc..Module-1 Group to update: MyResource..MyDesc2..Module-1 Verify that only the second part MyDesc was changed.
370      *
371      * @param currentGroupName
372      * @param groupUpdateName
373      * @return
374      */
375     private Either<Boolean, ResponseFormat> validateGroupName(String currentGroupName, String groupUpdateName, boolean isforceNameModification) {
376         try {
377             // Check if the group name is in old format.
378             if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupUpdateName).matches()) {
379                 log.error("Group name {} is in old format", groupUpdateName);
380                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME, groupUpdateName));
381             }
382             // Check that name pats 1 and 3 did not changed (only the second
383
384             // part can be changed)
385
386             // But verify before that the current group format is the new one
387             if (!Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(currentGroupName).matches()) {
388                 String[] split1 = currentGroupName.split(GROUP_DELIMITER_REGEX);
389                 String currentResourceName = split1[0];
390                 String currentCounter = split1[2];
391                 String[] split2 = groupUpdateName.split(GROUP_DELIMITER_REGEX);
392                 String groupUpdateResourceName = split2[0];
393                 String groupUpdateCounter = split2[2];
394                 if (!isforceNameModification) {            //if not forced ,allow name prefix&suffix validation [no changes]
395                     if (!currentResourceName.equals(groupUpdateResourceName)) {
396                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentResourceName));
397                     }
398                     if (!currentCounter.equals(groupUpdateCounter)) {
399                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentCounter));
400                     }
401                 }
402             }
403             return Either.left(true);
404         } catch (Exception e) {
405             log.error("Error valiadting group name", e);
406             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
407         }
408     }
409
410     /**
411      * associate artifacts to a given group
412      *
413      * @param componentId
414      * @param userId
415      * @param componentType
416      * @param inTransaction
417      * @return
418      */
419     public Either<GroupDefinitionInfo, ResponseFormat> getGroupWithArtifactsById(ComponentTypeEnum componentType, String componentId, String groupId,
420                                                                                  String userId, boolean inTransaction) {
421         Either<GroupDefinitionInfo, ResponseFormat> result = null;
422         // Validate user exist
423         validateUserExists(userId);
424         // Validate component exist
425         org.openecomp.sdc.be.model.Component component = null;
426         try {
427             ComponentParametersView componentParametersView = new ComponentParametersView();
428             componentParametersView.disableAll();
429             componentParametersView.setIgnoreGroups(false);
430             componentParametersView.setIgnoreArtifacts(false);
431             componentParametersView.setIgnoreUsers(false);
432             component = validateComponentExists(componentId, componentType, componentParametersView);
433             Either<GroupDefinition, StorageOperationStatus> groupEither = findGroupOnComponent(component, groupId);
434             if (groupEither.isRight()) {
435                 log.debug("Failed to find group {} under component {}", groupId, component.getUniqueId());
436                 BeEcompErrorManager.getInstance()
437                     .logInvalidInputError(GET_GROUP, "group  " + groupId + " not found under component " + component.getUniqueId(),
438                         ErrorSeverity.INFO);
439                 String componentTypeForResponse = getComponentTypeForResponse(component);
440                 result = Either.right(
441                     componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, groupId, component.getSystemName(), componentTypeForResponse));
442                 return result;
443             }
444             GroupDefinition group = groupEither.left().value();
445             List<GroupProperty> props = group.convertToGroupProperties();
446             Boolean isBase = isBaseProp(component, props);
447             List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
448             List<ArtifactDefinition> artifactsFromComponent = new ArrayList<>();
449             List<String> artifactsIds = group.getArtifacts();
450             Map<String, ArtifactDefinition> deploymentArtifacts = null;
451             if (MapUtils.isNotEmpty(component.getDeploymentArtifacts())) {
452                 deploymentArtifacts = component.getDeploymentArtifacts().values().stream()
453                     .collect(Collectors.toMap(ArtifactDataDefinition::getUniqueId, a -> a));
454             }
455             if (artifactsIds != null && !artifactsIds.isEmpty()) {
456                 for (String id : artifactsIds) {
457                     if (deploymentArtifacts == null || !deploymentArtifacts.containsKey(id)) {
458                         log.debug("Failed to get artifact {} . Status is {} ", id, StorageOperationStatus.NOT_FOUND);
459                         ResponseFormat responseFormat = componentsUtils
460                             .getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND));
461                         result = Either.right(responseFormat);
462                         return result;
463                     }
464                     artifactsFromComponent.add(deploymentArtifacts.get(id));
465                 }
466                 addArtifactsToList(artifacts, artifactsFromComponent);
467             }
468             GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
469             resultInfo.setIsBase(isBase);
470             if (!artifacts.isEmpty()) {
471                 resultInfo.setArtifacts(artifacts);
472             }
473             result = Either.left(resultInfo);
474             return result;
475         } finally {
476             closeTransaction(inTransaction, result);
477         }
478     }
479
480     private void addArtifactsToList(List<ArtifactDefinitionInfo> artifacts, List<ArtifactDefinition> artifactsFromComponent) {
481         artifactsFromComponent.forEach(a -> artifacts.add(new ArtifactDefinitionInfo(a)));
482     }
483
484     private Boolean isBaseProp(Component component, List<GroupProperty> props) {
485         Boolean isBase = null;
486         if (CollectionUtils.isNotEmpty(props)) {
487             Optional<GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
488             if (isBasePropOp.isPresent()) {
489                 GroupProperty propIsBase = isBasePropOp.get();
490                 isBase = Boolean.parseBoolean(propIsBase.getValue());
491             } else {
492                 BeEcompErrorManager.getInstance()
493                     .logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
494             }
495         }
496         return isBase;
497     }
498
499     private Either<GroupDefinition, StorageOperationStatus> findGroupOnComponent(Component component, String groupId) {
500         Either<GroupDefinition, StorageOperationStatus> result = null;
501         if (CollectionUtils.isNotEmpty(component.getGroups())) {
502             Optional<GroupDefinition> foundGroup = component.getGroups().stream().filter(g -> g.getUniqueId().equals(groupId)).findFirst();
503             if (foundGroup.isPresent()) {
504                 result = Either.left(foundGroup.get());
505             }
506         }
507         if (result == null) {
508             result = Either.right(StorageOperationStatus.NOT_FOUND);
509         }
510         return result;
511     }
512
513     public Either<Boolean, ResponseFormat> validateGenerateVfModuleGroupNames(List<ArtifactTemplateInfo> allGroups, String resourceSystemName,
514                                                                               int startGroupCounter) {
515         Either<Boolean, ResponseFormat> validateGenerateGroupNamesRes = Either.left(true);
516         Collections.sort(allGroups, ArtifactTemplateInfo::compareByGroupName);
517         for (ArtifactTemplateInfo group : allGroups) {
518             Either<String, ResponseFormat> validateGenerateGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName,
519                 group.getDescription(), startGroupCounter++);
520             if (validateGenerateGroupNameRes.isRight()) {
521                 validateGenerateGroupNamesRes = Either.right(validateGenerateGroupNameRes.right().value());
522                 break;
523             }
524             group.setGroupName(validateGenerateGroupNameRes.left().value());
525         }
526         return validateGenerateGroupNamesRes;
527     }
528
529     /**
530      * Generate module name from resourceName, description and counter
531      *
532      * @param resourceSystemName
533      * @param description
534      * @param groupCounter
535      * @return
536      */
537     private Either<String, ResponseFormat> validateGenerateVfModuleGroupName(String resourceSystemName, String description, int groupCounter) {
538         Either<String, ResponseFormat> validateGenerateGroupNameRes;
539         if (resourceSystemName != null && description != null && Pattern.compile(Constants.MODULE_DESC_PATTERN).matcher(description).matches()) {
540             final String fileName = description.replaceAll(GROUP_DELIMITER_REGEX, "\\.");
541             validateGenerateGroupNameRes = Either
542                 .left(String.format(Constants.MODULE_NAME_FORMAT, resourceSystemName, FilenameUtils.removeExtension(fileName), groupCounter));
543         } else {
544             validateGenerateGroupNameRes = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME));
545         }
546         return validateGenerateGroupNameRes;
547     }
548
549     Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNames(Map<String, GroupDefinition> groups, String resourceSystemName) {
550         Map<String, GroupDefinition> updatedNamesGroups = new HashMap<>();
551         Either<Map<String, GroupDefinition>, ResponseFormat> result = Either.left(updatedNamesGroups);
552         for (Entry<String, GroupDefinition> groupEntry : groups.entrySet()) {
553             GroupDefinition curGroup = groupEntry.getValue();
554             String groupType = curGroup.getType();
555             String groupName = groupEntry.getKey();
556             int counter;
557             String description;
558             Either<String, ResponseFormat> newGroupNameRes;
559             if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && !Pattern.compile(Constants.MODULE_NEW_NAME_PATTERN).matcher(groupName)
560                 .matches()) {
561                 if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupEntry.getKey()).matches()) {
562                     counter = Integer.parseInt(groupEntry.getKey().split(Constants.MODULE_NAME_DELIMITER)[1]);
563                     description = curGroup.getDescription();
564                 } else {
565                     counter = getNextVfModuleNameCounter(updatedNamesGroups);
566                     description = groupName;
567                 }
568                 newGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, description, counter);
569                 if (newGroupNameRes.isRight()) {
570                     log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
571                     loggerSupportability.log(LogLevel.INFO, LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML.getName(), StatusCode.ERROR.name(),
572                         "Failed to generate new vf module group name. Status is: " + newGroupNameRes.right().value());
573                     result = Either.right(newGroupNameRes.right().value());
574                     break;
575                 }
576                 groupName = newGroupNameRes.left().value();
577                 curGroup.setName(groupName);
578             }
579             updatedNamesGroups.put(groupName, curGroup);
580         }
581         return result;
582     }
583
584     public int getNextVfModuleNameCounter(Map<String, GroupDefinition> groups) {
585         int counter = 0;
586         if (groups != null && !groups.isEmpty()) {
587             counter = getNextVfModuleNameCounter(groups.values());
588         }
589         return counter;
590     }
591
592     public int getNextVfModuleNameCounter(Collection<GroupDefinition> groups) {
593         int counter = 0;
594         if (groups != null && !groups.isEmpty()) {
595             List<Integer> counters = groups.stream().filter(
596                 group -> Pattern.compile(Constants.MODULE_NEW_NAME_PATTERN).matcher(group.getName()).matches() || Pattern
597                     .compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(group.getName()).matches())
598                 .map(group -> Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1])).collect(toList());
599             counter = (counters == null || counters.isEmpty()) ? 0 : counters.stream().max(Integer::compare).get() + 1;
600         }
601         return counter;
602     }
603
604     public Either<List<GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesOnGraph(List<GroupDefinition> groups, Component component) {
605         List<GroupDefinition> updatedGroups = new ArrayList<>();
606         for (GroupDefinition group : groups) {
607             String groupType = group.getType();
608             String oldGroupName = group.getName();
609             String newGroupName;
610             Either<String, ResponseFormat> newGroupNameRes;
611             int counter;
612             if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(oldGroupName)
613                 .matches()) {
614                 counter = Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1]);
615                 newGroupNameRes = validateGenerateVfModuleGroupName(component.getSystemName(), group.getDescription(), counter);
616                 if (newGroupNameRes.isRight()) {
617                     log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
618                     break;
619                 }
620                 newGroupName = newGroupNameRes.left().value();
621                 group.setName(newGroupName);
622             }
623             updatedGroups.add(group);
624         }
625         return Either.left(updatedGroups);
626     }
627
628     public Either<GroupDefinitionInfo, ResponseFormat> getGroupInstWithArtifactsById(ComponentTypeEnum componentType, String componentId,
629                                                                                      String componentInstanceId, String groupInstId, String userId,
630                                                                                      boolean inTransaction) {
631         Either<GroupDefinitionInfo, ResponseFormat> result = null;
632         // Validate user exist
633         validateUserExists(userId);
634         // Validate component exist
635         org.openecomp.sdc.be.model.Component component;
636         try {
637             ComponentParametersView componentParametersView = new ComponentParametersView();
638             componentParametersView.disableAll();
639             componentParametersView.setIgnoreUsers(false);
640             componentParametersView.setIgnoreComponentInstances(false);
641             componentParametersView.setIgnoreArtifacts(false);
642             component = validateComponentExists(componentId, componentType, componentParametersView);
643             Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceRes = findComponentInstanceAndGroupInstanceOnComponent(
644                 component, componentInstanceId, groupInstId);
645             if (findComponentInstanceAndGroupInstanceRes.isRight()) {
646                 log.debug("Failed to get group {} . Status is {} ", groupInstId, findComponentInstanceAndGroupInstanceRes.right().value());
647                 ResponseFormat responseFormat = componentsUtils
648                     .getResponseFormat(componentsUtils.convertFromStorageResponse(findComponentInstanceAndGroupInstanceRes.right().value()));
649                 result = Either.right(responseFormat);
650                 return result;
651             }
652             GroupInstance group = findComponentInstanceAndGroupInstanceRes.left().value().getRight();
653             Boolean isBase = isBaseProperty(component, group);
654             List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
655             List<String> artifactsIds = group.getArtifacts();
656             if (artifactsIds != null && !artifactsIds.isEmpty()) {
657                 List<ComponentInstance> instances = component.getComponentInstances();
658                 if (instances != null) {
659                     instances.stream().filter(i -> i.getUniqueId().equals(componentInstanceId)).findFirst()
660                         .ifPresent(f -> getFirstComponentInstance(group, artifacts, artifactsIds, f));
661                 }
662             }
663             GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
664             resultInfo.setIsBase(isBase);
665             if (!artifacts.isEmpty()) {
666                 resultInfo.setArtifacts(artifacts);
667             }
668             result = Either.left(resultInfo);
669             return result;
670         } finally {
671             closeTransaction(inTransaction, result);
672         }
673     }
674
675     private void getFirstComponentInstance(GroupInstance group, List<ArtifactDefinitionInfo> artifacts, List<String> artifactsIds,
676                                            ComponentInstance ci) {
677         Map<String, ArtifactDefinition> deploymentArtifacts = ci.getDeploymentArtifacts();
678         artifactsIds.forEach(id -> deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst()
679             .ifPresent(g -> artifacts.add(new ArtifactDefinitionInfo(g))));
680         List<String> instArtifactsIds = group.getGroupInstanceArtifacts();
681         instArtifactsIds.forEach(id -> deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst()
682             .ifPresent(g -> artifacts.add(new ArtifactDefinitionInfo(g))));
683     }
684
685     private Boolean isBaseProperty(Component component, GroupInstance group) {
686         Boolean isBase = null;
687         List<? extends GroupProperty> props = group.convertToGroupInstancesProperties();
688         if (props != null && !props.isEmpty()) {
689             Optional<? extends GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
690             if (isBasePropOp.isPresent()) {
691                 GroupProperty propIsBase = isBasePropOp.get();
692                 isBase = Boolean.parseBoolean(propIsBase.getValue());
693             } else {
694                 BeEcompErrorManager.getInstance()
695                     .logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
696             }
697         }
698         return isBase;
699     }
700
701     private void closeTransaction(boolean inTransaction, Either<GroupDefinitionInfo, ResponseFormat> result) {
702         if (!inTransaction) {
703             if (result == null || result.isRight()) {
704                 log.debug("Going to execute rollback on create group.");
705                 janusGraphDao.rollback();
706             } else {
707                 log.debug("Going to execute commit on create group.");
708                 janusGraphDao.commit();
709             }
710         }
711     }
712
713     private Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceOnComponent(
714         Component component, String componentInstanceId, String groupInstId) {
715         Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> result = null;
716         if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
717             Optional<GroupInstance> foundGroup;
718             Optional<ComponentInstance> foundComponent = component.getComponentInstances().stream()
719                 .filter(ci -> ci.getUniqueId().equals(componentInstanceId)).findFirst();
720             if (foundComponent.isPresent() && CollectionUtils.isNotEmpty(foundComponent.get().getGroupInstances())) {
721                 foundGroup = foundComponent.get().getGroupInstances().stream().filter(gi -> gi.getUniqueId().equals(groupInstId)).findFirst();
722                 if (foundGroup.isPresent()) {
723                     result = Either.left(new ImmutablePair<>(foundComponent.get(), foundGroup.get()));
724                 }
725             }
726         }
727         if (result == null) {
728             result = Either.right(StorageOperationStatus.NOT_FOUND);
729         }
730         return result;
731     }
732
733     private Boolean validateMinMaxAndInitialCountPropertyLogic(Map<PropertyNames, String> newValues, Map<PropertyNames, String> currValues,
734                                                                Map<PropertyNames, String> parentValues) {
735         for (Entry<PropertyNames, String> entry : newValues.entrySet()) {
736             PropertyNames currPropertyName = entry.getKey();
737             if (currPropertyName == PropertyNames.MIN_INSTANCES) {
738                 String minValue = parentValues.get(PropertyNames.MIN_INSTANCES);
739                 String maxValue = getMaxValue(newValues, currValues);
740                 validateValueInRange(new ImmutablePair<>(currPropertyName, entry.getValue()),
741                     new ImmutablePair<>(PropertyNames.MIN_INSTANCES, minValue), new ImmutablePair<>(PropertyNames.MAX_INSTANCES, maxValue));
742             } else if (currPropertyName == PropertyNames.INITIAL_COUNT) {
743                 String minValue = newValues.containsKey(PropertyNames.MIN_INSTANCES) ? newValues.get(PropertyNames.MIN_INSTANCES)
744                     : currValues.get(PropertyNames.MIN_INSTANCES);
745                 String maxValue = newValues.containsKey(PropertyNames.MAX_INSTANCES) ? newValues.get(PropertyNames.MAX_INSTANCES)
746                     : currValues.get(PropertyNames.MAX_INSTANCES);
747                 validateValueInRange(new ImmutablePair<>(currPropertyName, entry.getValue()),
748                     new ImmutablePair<>(PropertyNames.MIN_INSTANCES, minValue), new ImmutablePair<>(PropertyNames.MAX_INSTANCES, maxValue));
749             } else if (currPropertyName == PropertyNames.MAX_INSTANCES) {
750                 String minValue = getMinValue(newValues, currValues);
751                 String maxValue = parentValues.get(PropertyNames.MAX_INSTANCES);
752                 validateValueInRange(new ImmutablePair<>(currPropertyName, entry.getValue()),
753                     new ImmutablePair<>(PropertyNames.MIN_INSTANCES, minValue), new ImmutablePair<>(PropertyNames.MAX_INSTANCES, maxValue));
754             }
755         }
756         return true;
757     }
758
759     private String getMaxValue(Map<PropertyNames, String> newValues, Map<PropertyNames, String> currValues) {
760         return newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MAX_INSTANCES)
761             : currValues.get(PropertyNames.INITIAL_COUNT);
762     }
763
764     private String getMinValue(Map<PropertyNames, String> newValues, Map<PropertyNames, String> currValues) {
765         return newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MIN_INSTANCES)
766             : currValues.get(PropertyNames.INITIAL_COUNT);
767     }
768
769     private Boolean validateValueInRange(ImmutablePair<PropertyNames, String> newValue, ImmutablePair<PropertyNames, String> min,
770                                          ImmutablePair<PropertyNames, String> max) {
771         final String warnMessage = "Failed to validate {} as property value of {}. It must be not higher than {}, and not lower than {}.";
772         int newValueInt = parseIntValue(newValue.getValue(), newValue.getKey());
773         int minInt = parseIntValue(min.getValue(), min.getKey());
774         int maxInt = parseIntValue(max.getValue(), max.getKey());
775         if (newValueInt < 0 || minInt < 0 || maxInt < 0) {
776             throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY);
777         } else if (newValueInt < minInt || newValueInt > maxInt) {
778             log.debug(warnMessage, newValue.getValue(), newValue.getKey().getPropertyName(), min.getValue(), max.getValue());
779             throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_MIN_MAX_INSTANCES_PROPERTY_VALUE,
780                 newValue.getKey().getPropertyName(), maxInt == Integer.MAX_VALUE ? Constants.UNBOUNDED : max.getValue(), min.getValue());
781         }
782         return true;
783     }
784
785     private int parseIntValue(String value, PropertyNames propertyName) {
786         int result;
787         if (propertyName == PropertyNames.MAX_INSTANCES) {
788             result = convertIfUnboundMax(value);
789         } else if (NumberUtils.isNumber(value)) {
790             result = Integer.parseInt(value);
791         } else {
792             result = -1;
793         }
794         return result;
795     }
796
797     /**
798      * validates received new property values and updates group instance in case of success
799      *
800      * @param oldGroupInstance
801      * @param newProperties
802      * @return
803      */
804     public Either<GroupInstance, ResponseFormat> validateAndUpdateGroupInstancePropertyValues(String componentId, String instanceId,
805                                                                                               GroupInstance oldGroupInstance,
806                                                                                               List<GroupInstanceProperty> newProperties) {
807         final Either<Component, StorageOperationStatus> ownerComponentEither =
808             toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll);
809         if (ownerComponentEither.isRight()) {
810             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId);
811             final ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(ownerComponentEither.right().value());
812             return Either.right(componentsUtils.getResponseFormat(actionStatus, componentId));
813         }
814
815         final List<GroupInstanceProperty> validatedReducedNewProperties =
816             validateReduceGroupInstancePropertiesBeforeUpdate(ownerComponentEither.left().value(), oldGroupInstance, newProperties);
817         final Either<GroupInstance, StorageOperationStatus> updateGroupInstanceResult = groupsOperation
818             .updateGroupInstancePropertyValuesOnGraph(componentId, instanceId, oldGroupInstance, validatedReducedNewProperties);
819         if (updateGroupInstanceResult.isRight()) {
820             log.debug("Failed to update group instance {} property values. ", oldGroupInstance.getName());
821             return Either
822                 .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateGroupInstanceResult.right().value())));
823         }
824         return Either.left(updateGroupInstanceResult.left().value());
825     }
826
827     private List<GroupInstanceProperty> validateReduceGroupInstancePropertiesBeforeUpdate(final Component groupOwnerComponent,
828                                                                                           final GroupInstance oldGroupInstance,
829                                                                                           final List<GroupInstanceProperty> newProperties) {
830         Boolean validationRes = null;
831         List<GroupInstanceProperty> actionResult = null;
832         Map<String, GroupInstanceProperty> existingProperties = oldGroupInstance.convertToGroupInstancesProperties().stream()
833             .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
834         Map<PropertyNames, String> newPropertyValues = new EnumMap<>(PropertyNames.class);
835         List<GroupInstanceProperty> reducedProperties = new ArrayList<>();
836         String currPropertyName;
837         try {
838             for (GroupInstanceProperty currNewProperty : newProperties) {
839                 currPropertyName = currNewProperty.getName();
840                 validationRes = handleAndAddProperty(groupOwnerComponent, reducedProperties, newPropertyValues,
841                     currNewProperty, existingProperties.get(currPropertyName));
842             }
843             if (validationRes == null || validationRes) {
844                 Map<PropertyNames, String> existingPropertyValues = new EnumMap<>(PropertyNames.class);
845                 Map<PropertyNames, String> parentPropertyValues = new EnumMap<>(PropertyNames.class);
846                 fillValuesAndParentValuesFromExistingProperties(existingProperties, existingPropertyValues, parentPropertyValues);
847                 validationRes = validateMinMaxAndInitialCountPropertyLogic(newPropertyValues, existingPropertyValues, parentPropertyValues);
848             }
849             if (validationRes) {
850                 actionResult = reducedProperties;
851             }
852         } catch (Exception e) {
853             log.error("Exception occured during validation and reducing group instance properties. The message is {}", e.getMessage(), e);
854             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
855         }
856         return actionResult;
857     }
858
859     private void fillValuesAndParentValuesFromExistingProperties(Map<String, GroupInstanceProperty> existingProperties,
860                                                                  Map<PropertyNames, String> propertyValues,
861                                                                  Map<PropertyNames, String> parentPropertyValues) {
862         PropertyNames[] allPropertyNames = PropertyNames.values();
863         for (PropertyNames name : allPropertyNames) {
864             if (isUpdatable(name)) {
865                 propertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getValue()));
866                 parentPropertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getParentValue()));
867             }
868         }
869     }
870
871     private boolean handleAndAddProperty(final Component groupOwner, final List<GroupInstanceProperty> reducedProperties,
872                                          final Map<PropertyNames, String> newPropertyValues, final GroupInstanceProperty currNewProperty,
873                                          final GroupInstanceProperty currExistingProperty) {
874         final String currPropertyName = currNewProperty.getName();
875         final PropertyNames propertyName = PropertyNames.findName(currPropertyName);
876         try {
877             if (currExistingProperty == null) {
878                 log.warn("The value of property with the name {} cannot be updated. The property not found on group instance. ", currPropertyName);
879             } else if (isUpdatable(propertyName)) {
880                 validateAndUpdatePropertyValue(groupOwner, currNewProperty, currExistingProperty);
881                 addPropertyUpdatedValues(reducedProperties, propertyName, newPropertyValues, currNewProperty, currExistingProperty);
882             } else {
883                 validateImmutableProperty(currExistingProperty, currNewProperty);
884             }
885         } catch (final Exception e) {
886             log.error("Exception occurred during handle and adding property. The message is {}", e.getMessage(), e);
887             return false;
888         }
889         return true;
890     }
891
892     private boolean isUpdatable(PropertyNames updatablePropertyName) {
893         return updatablePropertyName != null
894             && updatablePropertyName.getUpdateBehavior().getLevelNumber() >= GroupInstancePropertyValueUpdateBehavior.UPDATABLE_ON_SERVICE_LEVEL
895             .getLevelNumber();
896     }
897
898     private void addPropertyUpdatedValues(List<GroupInstanceProperty> reducedProperties, PropertyNames propertyName,
899                                           Map<PropertyNames, String> newPropertyValues, GroupInstanceProperty newProperty,
900                                           GroupInstanceProperty existingProperty) {
901         String newValue = newProperty.getValue();
902         if (!newValue.equals(String.valueOf(existingProperty.getValue()))) {
903             newProperty.setValueUniqueUid(existingProperty.getValueUniqueUid());
904             reducedProperties.add(newProperty);
905         }
906         if (!isEmptyMinInitialCountValue(propertyName, newValue)) {
907             newPropertyValues.put(propertyName, newValue);
908         }
909     }
910
911     private boolean isEmptyMinInitialCountValue(PropertyNames propertyName, String newValue) {
912         boolean result = false;
913         if ((propertyName == PropertyNames.MIN_INSTANCES || propertyName == PropertyNames.INITIAL_COUNT) && !NumberUtils.isNumber(newValue)) {
914             result = true;
915         }
916         return result;
917     }
918
919     private int convertIfUnboundMax(String value) {
920         int result;
921         if (!NumberUtils.isNumber(value)) {
922             result = Integer.MAX_VALUE;
923         } else {
924             result = Integer.parseInt(value);
925         }
926         return result;
927     }
928
929     private void validateAndUpdatePropertyValue(final Component groupOwner, final GroupInstanceProperty newProperty,
930                                                 final GroupInstanceProperty existingProperty) {
931         String parentValue = existingProperty.getParentValue();
932         newProperty.setParentValue(parentValue);
933         if (StringUtils.isEmpty(newProperty.getValue())) {
934             newProperty.setValue(parentValue);
935         }
936         if (StringUtils.isEmpty(existingProperty.getValue())) {
937             existingProperty.setValue(parentValue);
938         }
939         StorageOperationStatus status = groupOperation.validateAndUpdatePropertyValue(groupOwner, newProperty);
940         if (status != StorageOperationStatus.OK) {
941             log.debug("Failed to validate property value {} of property with name {}. Status is {}. ", newProperty.getValue(), newProperty.getName(),
942                 status);
943             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
944         }
945     }
946
947     private void validateImmutableProperty(GroupProperty oldProperty, GroupProperty newProperty) {
948         if (oldProperty.getValue() == null && newProperty.getValue() != null || oldProperty.getValue() != null && !oldProperty.getValue()
949             .equals(newProperty.getValue())) {
950             log.warn("The value of property with the name {} cannot be updated on service level. Going to ignore new property value {}. ",
951                 oldProperty.getName(), newProperty.getValue());
952         }
953     }
954
955     @LockingTransactional
956     public GroupDefinition createGroup(String componentId, ComponentTypeEnum componentTypeEnum, String groupType, String userId) {
957         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentTypeEnum, userId, CREATE_GROUP);
958         validateGroupTypePerComponent(groupType, component);
959         GroupTypeDefinition groupTypeDefinition = groupTypeOperation.getLatestGroupTypeByType(groupType, component.getModel(), false).left()
960             .on(se -> onGroupTypeNotFound(component));
961         boolean hasExistingGroups = CollectionUtils.isNotEmpty(component.getGroups());
962         GroupDefinition groupDefinition = new GroupDefinition();
963         groupDefinition.setType(groupType);
964         //find next valid counter
965         int nextCounter = 0;
966         if (hasExistingGroups) {
967             nextCounter = getNewGroupCounter(component);
968         }
969         String name = TopologyTemplateOperation.buildSubComponentName(component.getName(), groupType, nextCounter);
970         groupDefinition.setName(name);
971         groupDefinition.setDescription(groupTypeDefinition.getDescription());
972         groupDefinition.setInvariantName(name);
973         groupDefinition.setCreatedFrom(CreatedFrom.UI);
974         //Add default type properties
975         List<PropertyDefinition> groupTypeProperties = groupTypeDefinition.getProperties();
976         List<GroupProperty> properties = groupTypeProperties.stream().map(GroupProperty::new).collect(toList());
977         groupDefinition.convertFromGroupProperties(properties);
978         groupDefinition.convertCapabilityDefinitions(groupTypeDefinition.getCapabilities());
979         List<GroupDefinition> gdList;
980         if (toscaOperationFacade.canAddGroups(componentId)) {
981             gdList = addGroups(component, Arrays.asList(groupDefinition), false).left().on(this::onFailedGroupDBOperation);
982         } else {
983             //createGroups also creates an edge and vertex to store group data
984             gdList = createGroups(component, Arrays.asList(groupDefinition), false).left().on(this::onFailedGroupDBOperation);
985         }
986         return gdList.get(0);
987     }
988
989     private void validateGroupTypePerComponent(String groupType, Component component) {
990         String specificType = component.getComponentMetadataDefinition().getMetadataDataDefinition().getActualComponentType();
991         if (!component.isTopologyTemplate()) {
992             throw new ByActionStatusComponentException(ActionStatus.GROUP_TYPE_ILLEGAL_PER_COMPONENT, groupType, specificType);
993         }
994         Map<String, Set<String>> excludedGroupTypesMap = ConfigurationManager.getConfigurationManager().getConfiguration()
995             .getExcludedGroupTypesMapping();
996         if (MapUtils.isNotEmpty(excludedGroupTypesMap) && StringUtils.isNotEmpty(specificType)) {
997             Set<String> excludedGroupTypesPerComponent = excludedGroupTypesMap.get(specificType);
998             if (excludedGroupTypesPerComponent != null && excludedGroupTypesPerComponent.contains(groupType)) {
999                 throw new ByActionStatusComponentException(ActionStatus.GROUP_TYPE_ILLEGAL_PER_COMPONENT, groupType, specificType);
1000             }
1001         }
1002     }
1003
1004     private int getNewGroupCounter(Component component) {
1005         List<String> existingNames = component.getGroups().stream().map(GroupDataDefinition::getInvariantName).collect(toList());
1006         List<String> existingIds = component.getGroups().stream().map(GroupDataDefinition::getUniqueId).collect(toList());
1007         existingIds.addAll(existingNames);
1008         return Utils.getNextCounter(existingIds);
1009     }
1010
1011     @LockingTransactional
1012     public GroupDefinition updateGroup(String componentId, ComponentTypeEnum componentTypeEnum, String groupId, String userId,
1013                                        GroupDefinition updatedGroup) {
1014         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentTypeEnum, userId, UPDATE_GROUP);
1015         GroupDefinition existingGroup = findGroupOnComponent(component, groupId).left().on(se -> onGroupNotFoundInComponentError(component, groupId));
1016         String existingGroupName = existingGroup.getName();
1017         String updatedGroupName = updatedGroup.getName();
1018         assertNewNameIsValidAndUnique(existingGroupName, updatedGroupName, component);
1019         existingGroup.setName(updatedGroupName);
1020         return updateGroup(component, existingGroup, existingGroupName).left().on(this::onFailedUpdateGroupDBOperation);
1021     }
1022
1023     private void assertNewNameIsValidAndUnique(String currentGroupName, String updatedGroupName, Component component) {
1024         if (!ValidationUtils.validateResourceInstanceNameLength(updatedGroupName)) {
1025             throw new ByActionStatusComponentException(ActionStatus.EXCEEDS_LIMIT, "Group Name", ValidationUtils.RSI_NAME_MAX_LENGTH.toString());
1026         }
1027         if (!ValidationUtils.validateResourceInstanceName(updatedGroupName)) {
1028             throw new ByActionStatusComponentException(ActionStatus.INVALID_VF_MODULE_NAME, updatedGroupName);
1029         }
1030         if (!ComponentValidations.validateNameIsUniqueInComponent(currentGroupName, updatedGroupName, component)) {
1031             throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, "Group", updatedGroupName);
1032         }
1033     }
1034
1035     @LockingTransactional
1036     public GroupDefinition deleteGroup(String componentId, ComponentTypeEnum componentTypeEnum, String groupId, String userId) {
1037         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentTypeEnum, userId, DELETE_GROUP);
1038         GroupDefinition groupDefinition = findGroupOnComponent(component, groupId).left()
1039             .on(se -> onGroupNotFoundInComponentError(component, groupId));
1040         List<GroupDefinition> gdList = deleteGroups(component, java.util.Arrays.asList(groupDefinition)).left().on(this::onFailedGroupDBOperation);
1041         updatePolicyTargetReferencingDeletedGroup(groupId, component);
1042         return gdList.get(0);
1043     }
1044
1045     private List<GroupDefinition> onFailedGroupDBOperation(ResponseFormat responseFormat) {
1046         janusGraphDao.rollback();
1047         throw new ByResponseFormatComponentException(responseFormat);
1048     }
1049
1050     private GroupDefinition onFailedUpdateGroupDBOperation(ResponseFormat responseFormat) {
1051         janusGraphDao.rollback();
1052         throw new ByResponseFormatComponentException(responseFormat);
1053     }
1054
1055     private GroupDefinition onGroupNotFoundInComponentError(Component component, String groupId) {
1056         throw new ByActionStatusComponentException(ActionStatus.GROUP_IS_MISSING, groupId, component.getSystemName(),
1057             getComponentTypeForResponse(component));
1058     }
1059
1060     private GroupTypeDefinition onGroupTypeNotFound(Component component) {
1061         throw new ByActionStatusComponentException(ActionStatus.GROUP_TYPE_IS_INVALID, component.getSystemName(),
1062             component.getComponentType().toString());
1063     }
1064
1065     private void updatePolicyTargetReferencingDeletedGroup(String groupId, Component component) {
1066         log.debug("#updatePolicyTargetReferencingDeletedGroup - removing all component {} policy targets referencing group {}",
1067             component.getUniqueId(), groupId);
1068         ActionStatus actionStatus = policyTargetsUpdateHandler.removePoliciesTargets(component, groupId, PolicyTargetType.GROUPS);
1069         if (ActionStatus.OK != actionStatus) {
1070             janusGraphDao.rollback();
1071             throw new ByActionStatusComponentException(actionStatus, groupId);
1072         }
1073     }
1074
1075     public Either<List<GroupDefinition>, ResponseFormat> createGroups(Component component, final List<GroupDefinition> groupDefinitions,
1076                                                                       boolean fromCsar) {
1077         Map<String, GroupDataDefinition> groups = new HashMap<>();
1078         Either<List<GroupDefinition>, ResponseFormat> result = null;
1079         Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult;
1080
1081         // handle groups and convert to tosca data
1082         if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1083             for (GroupDefinition groupDefinition : groupDefinitions) {
1084                 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, groupDefinition,
1085                     componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel()));
1086                 if (handleGroupRes.isRight()) {
1087                     result = Either.right(handleGroupRes.right().value());
1088                     break;
1089                 }
1090                 GroupDefinition handledGroup = handleGroupRes.left().value();
1091                 groups.put(handledGroup.getInvariantName(), new GroupDataDefinition(handledGroup));
1092             }
1093         }
1094         if (result == null) {
1095             createGroupsResult = groupsOperation.createGroups(component, groups);
1096             if (createGroupsResult.isRight()) {
1097                 result = Either
1098                     .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1099             }
1100         }
1101         if (result == null) {
1102             addCalculatedCapabilitiesWithPropertiesToComponent(component, groupDefinitions, fromCsar);
1103         }
1104         if (result == null) {
1105             result = Either.left(groupDefinitions);
1106         }
1107         component.setGroups(groupDefinitions);
1108         return result;
1109     }
1110
1111     private void updateCalculatedCapabilitiesWithPropertiesOnComponent(Component component, final List<GroupDefinition> groupDefinitions,
1112                                                                        boolean fromCsar) {
1113         groupDefinitions.forEach(GroupDefinition::updateEmptyCapabilitiesOwnerFields);
1114         StorageOperationStatus status = groupsOperation
1115             .updateCalculatedCapabilitiesWithProperties(component.getUniqueId(), extractCapabilitiesFromGroups(groupDefinitions),
1116                 extractCapabilityPropertiesFromGroups(groupDefinitions, fromCsar));
1117         if (status != StorageOperationStatus.OK) {
1118             log.error(
1119                 "#updateCalculatedCapabilitiesWithPropertiesOnComponent - failed to update the groups' calculated capabilities with the properties on the component {}. ",
1120                 component.getUniqueId());
1121             rollbackWithException(componentsUtils.convertFromStorageResponse(status));
1122         }
1123     }
1124
1125     private void addCalculatedCapabilitiesWithPropertiesToComponent(Component component, final List<GroupDefinition> groupDefinitions,
1126                                                                     boolean fromCsar) {
1127         final List<GroupDefinition> nonNullGroupDefinitions = (groupDefinitions == null) ? Collections.emptyList() : groupDefinitions;
1128         nonNullGroupDefinitions.forEach(GroupDefinition::updateEmptyCapabilitiesOwnerFields);
1129         StorageOperationStatus status = groupsOperation
1130             .addCalculatedCapabilitiesWithProperties(component.getUniqueId(), extractCapabilitiesFromGroups(nonNullGroupDefinitions),
1131                 extractCapabilityPropertiesFromGroups(nonNullGroupDefinitions, fromCsar));
1132         if (status != StorageOperationStatus.OK) {
1133             log.error(
1134                 "#addCalculatedCapabilitiesWithPropertiesToComponent - failed to add the groups' calculated capabilities with the properties to the component {}. ",
1135                 component.getUniqueId());
1136             rollbackWithException(componentsUtils.convertFromStorageResponse(status));
1137         }
1138     }
1139
1140     private void deleteCalculatedCapabilitiesWithPropertiesFromComponent(Component component, final List<GroupDefinition> groupDefinitions) {
1141         StorageOperationStatus status = groupsOperation.deleteCalculatedCapabilitiesWithProperties(component.getUniqueId(), groupDefinitions);
1142         if (status != StorageOperationStatus.OK) {
1143             log.error(
1144                 "#deleteCalculatedCapabilitiesWithPropertiesFromComponent - failed to remove the groups' calculated capabilities with the properties from the component {}. ",
1145                 component.getUniqueId());
1146             rollbackWithException(componentsUtils.convertFromStorageResponse(status));
1147         }
1148     }
1149
1150     public Either<List<GroupDefinition>, ResponseFormat> addGroups(Component component, final List<GroupDefinition> groupDefinitions,
1151                                                                    boolean fromCsar) {
1152         Either<List<GroupDefinition>, ResponseFormat> result = null;
1153         Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1154         List<GroupDataDefinition> groups = new ArrayList<>();
1155         // handle groups and convert to tosca data
1156         if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1157             for (GroupDefinition groupDefinition : groupDefinitions) {
1158                 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, groupDefinition,
1159                     componentsUtils.getAllDataTypes(applicationDataTypeCache, component.getModel()));
1160                 if (handleGroupRes.isRight()) {
1161                     result = Either.right(handleGroupRes.right().value());
1162                     break;
1163                 }
1164                 GroupDefinition handledGroup = handleGroupRes.left().value();
1165                 groups.add(new GroupDataDefinition(handledGroup));
1166             }
1167         }
1168         if (result == null) {
1169             createGroupsResult = groupsOperation.addGroups(component, groups);
1170             if (createGroupsResult.isRight()) {
1171                 result = Either
1172                     .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1173             }
1174             component.addGroups(createGroupsResult.left().value());
1175         }
1176         if (result == null) {
1177             addCalculatedCapabilitiesWithPropertiesToComponent(component, groupDefinitions, fromCsar);
1178         }
1179         if (result == null) {
1180             result = Either.left(groupDefinitions);
1181         }
1182         return result;
1183     }
1184
1185     public Either<List<GroupDefinition>, ResponseFormat> deleteGroups(Component component, List<GroupDefinition> groupDefinitions) {
1186         Either<List<GroupDefinition>, StorageOperationStatus> deleteGroupsResult;
1187         deleteGroupsResult = groupsOperation.deleteGroups(component, groupDefinitions.stream().map(GroupDataDefinition::new).collect(toList()));
1188         if (deleteGroupsResult.isRight()) {
1189             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteGroupsResult.right().value())));
1190         } else {
1191             deleteCalculatedCapabilitiesWithPropertiesFromComponent(component, groupDefinitions);
1192         }
1193         if (component.getGroups() != null) {
1194             component.getGroups().removeAll(deleteGroupsResult.left().value());
1195         }
1196         return Either.left(deleteGroupsResult.left().value());
1197     }
1198
1199     /**
1200      * Update specific group version
1201      *
1202      * @param fromCsar TODO
1203      */
1204     public Either<List<GroupDefinition>, ResponseFormat> updateGroups(Component component, List<GroupDefinition> groupDefinitions, boolean fromCsar) {
1205         Either<List<GroupDefinition>, ResponseFormat> result = null;
1206         Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult;
1207         createGroupsResult = groupsOperation
1208             .updateGroups(component, groupDefinitions.stream().map(GroupDataDefinition::new).collect(toList()), PromoteVersionEnum.MINOR);
1209         if (createGroupsResult.isRight()) {
1210             result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1211         }
1212         if (result == null) {
1213             updateCalculatedCapabilitiesWithPropertiesOnComponent(component, groupDefinitions, fromCsar);
1214         }
1215         if (result == null) {
1216             result = Either.left(groupDefinitions);
1217         }
1218         return result;
1219     }
1220
1221     private Either<GroupDefinition, ResponseFormat> handleGroup(Component component, GroupDefinition groupDefinition,
1222                                                                 Map<String, DataTypeDefinition> allDAtaTypes) {
1223         log.trace("Going to create group {}", groupDefinition);
1224         loggerSupportability.log(LoggerSupportabilityActions.CREATE_GROUP_POLICY, component.getComponentMetadataForSupportLog(), StatusCode.STARTED,
1225             "Start to create group: {}", groupDefinition.getName() + " for component " + component.getName());
1226         // 3. verify group not already exist
1227         String groupDefinitionName = groupDefinition.getName();
1228         if (groupExistsInComponent(groupDefinitionName, component)) {
1229             String componentTypeForResponse = getComponentTypeForResponse(component);
1230             return Either.right(componentsUtils
1231                 .getResponseFormat(ActionStatus.GROUP_ALREADY_EXIST, groupDefinitionName, component.getNormalizedName(), componentTypeForResponse));
1232         }
1233         // 4. verify type of group exist
1234         String groupType = groupDefinition.getType();
1235         if (StringUtils.isEmpty(groupType)) {
1236             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupDefinitionName));
1237         }
1238         Either<GroupTypeDefinition, StorageOperationStatus> getGroupType = groupTypeOperation.getLatestGroupTypeByType(groupType, component.getModel(), true);
1239         if (getGroupType.isRight()) {
1240             StorageOperationStatus status = getGroupType.right().value();
1241             if (status == StorageOperationStatus.NOT_FOUND) {
1242                 loggerSupportability
1243                     .log(LoggerSupportabilityActions.CREATE_GROUP_POLICY, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
1244                         "group {} cannot be found", groupDefinition.getName());
1245                 BeEcompErrorManager.getInstance()
1246                     .logInvalidInputError(CREATE_GROUP, "group type " + groupType + " cannot be found", ErrorSeverity.INFO);
1247                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, groupType));
1248             } else {
1249                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1250             }
1251         }
1252         // 6. verify the component instances type are allowed according to
1253
1254         // the member types in the group type
1255         GroupTypeDefinition groupTypeDefinition = getGroupType.left().value();
1256         Either<Boolean, ResponseFormat> areValidMembers = verifyComponentInstancesAreValidMembers(component, groupDefinitionName,
1257             groupDefinition.getMembers(), groupTypeDefinition.getMembers());
1258         if (areValidMembers.isRight()) {
1259             ResponseFormat responseFormat = areValidMembers.right().value();
1260             return Either.right(responseFormat);
1261         }
1262         // 7. verify the artifacts belongs to the component
1263         Either<Boolean, ResponseFormat> areValidArtifacts = verifyArtifactsBelongsToComponent(component, groupDefinition.getArtifacts(),
1264             CREATE_GROUP);
1265         if (areValidArtifacts.isRight()) {
1266             ResponseFormat responseFormat = areValidArtifacts.right().value();
1267             return Either.right(responseFormat);
1268         }
1269         List<PropertyDefinition> groupTypeProperties = groupTypeDefinition.getProperties();
1270         List<GroupProperty> properties = groupDefinition.convertToGroupProperties();
1271         List<GroupProperty> updatedGroupTypeProperties = new ArrayList<>();
1272         if (CollectionUtils.isNotEmpty(properties)) {
1273             if (CollectionUtils.isEmpty(groupTypeProperties)) {
1274                 BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "group type does not have properties", ErrorSeverity.INFO);
1275                 loggerSupportability
1276                     .log(LoggerSupportabilityActions.CREATE_GROUP_POLICY, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
1277                         "group {} does not have properties ", groupDefinition.getName());
1278                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
1279                     DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.MATCH_NOT_FOUND))));
1280             }
1281             Map<String, PropertyDefinition> groupTypePropertiesMap = groupTypeProperties.stream()
1282                 .collect(Collectors.toMap(PropertyDefinition::getName, p -> p));
1283             Either<GroupProperty, JanusGraphOperationStatus> addPropertyResult;
1284             int i = 1;
1285             for (GroupProperty prop : properties) {
1286                 addPropertyResult = handleProperty(prop, groupTypePropertiesMap.get(prop.getName()), i, allDAtaTypes, groupType);
1287                 if (addPropertyResult.isRight()) {
1288                     BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "failed to validate property", ErrorSeverity.INFO);
1289                     return Either.right(componentsUtils.getResponseFormat(componentsUtils
1290                         .convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertyResult.right().value()))));
1291                 }
1292                 updatedGroupTypeProperties.add(addPropertyResult.left().value());
1293                 i++;
1294             }
1295         }
1296         if (groupDefinition.getUniqueId() == null) {
1297             String uid = UniqueIdBuilder.buildGroupingUid(component.getUniqueId(), groupDefinitionName);
1298             groupDefinition.setUniqueId(uid);
1299         }
1300         groupDefinition.convertFromGroupProperties(updatedGroupTypeProperties);
1301         groupDefinition.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID());
1302         groupDefinition.setGroupUUID(UniqueIdBuilder.generateUUID());
1303         groupDefinition.setVersion(INITIAL_VERSION);
1304         groupDefinition.setTypeUid(groupTypeDefinition.getUniqueId());
1305         loggerSupportability.log(LoggerSupportabilityActions.CREATE_GROUP_POLICY, component.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
1306             "group {} has been created ", groupDefinition.getName());
1307         return Either.left(groupDefinition);
1308     }
1309
1310     private Either<GroupProperty, JanusGraphOperationStatus> handleProperty(GroupProperty groupProperty, PropertyDefinition prop, Integer index,
1311                                                                             Map<String, DataTypeDefinition> allDataTypes, String groupType) {
1312         if (prop == null) {
1313             return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
1314         }
1315         String propertyType = prop.getType();
1316         String value = groupProperty.getValue();
1317         Either<String, JanusGraphOperationStatus> checkInnerType = propertyOperation.checkInnerType(prop);
1318         if (checkInnerType.isRight()) {
1319             JanusGraphOperationStatus status = checkInnerType.right().value();
1320             return Either.right(status);
1321         }
1322         String innerType = checkInnerType.left().value();
1323         log.debug("Before validateAndUpdatePropertyValue");
1324         Either<Object, Boolean> isValid = propertyOperation.validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes);
1325         log.debug("After validateAndUpdatePropertyValue. isValid = {}", isValid);
1326         String newValue = value;
1327         if (isValid.isRight()) {
1328             Boolean res = isValid.right().value();
1329             if (!res) {
1330                 return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
1331             }
1332         } else {
1333             Object object = isValid.left().value();
1334             if (object != null) {
1335                 newValue = object.toString();
1336             }
1337         }
1338         String uniqueId =
1339             shouldReconstructUniqueId(groupType) ? UniqueIdBuilder.buildGroupPropertyValueUid(prop.getUniqueId(), index) : prop.getUniqueId();
1340         groupProperty.setUniqueId(uniqueId);
1341         groupProperty.setValue(newValue);
1342         groupProperty.setType(prop.getType());
1343         groupProperty.setDefaultValue(prop.getDefaultValue());
1344         groupProperty.setDescription(prop.getDescription());
1345         groupProperty.setSchema(prop.getSchema());
1346         groupProperty.setPassword(prop.isPassword());
1347         groupProperty.setParentUniqueId(prop.getUniqueId());
1348         log.debug("Before adding property value to graph {}", groupProperty);
1349         return Either.left(groupProperty);
1350     }
1351     // For old groups we want to leave indexing of property
1352
1353     // For new groups we just need the types
1354     private boolean shouldReconstructUniqueId(String groupType) {
1355         return Constants.GROUP_TOSCA_HEAT.equals(groupType) || Constants.DEFAULT_GROUP_VF_MODULE.equals(groupType);
1356     }
1357 }