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