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