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