[SDC] rebase 1710 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  */
20
21 package org.openecomp.sdc.be.components.impl;
22
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Optional;
34 import java.util.Set;
35 import java.util.function.Function;
36 import java.util.regex.Pattern;
37 import java.util.stream.Collectors;
38
39 import org.apache.commons.collections.CollectionUtils;
40 import org.apache.commons.collections.MapUtils;
41 import org.apache.commons.io.FilenameUtils;
42 import org.apache.commons.lang.StringUtils;
43 import org.apache.commons.lang3.math.NumberUtils;
44 import org.apache.commons.lang3.tuple.ImmutablePair;
45 import org.codehaus.jackson.JsonGenerationException;
46 import org.codehaus.jackson.map.JsonMappingException;
47 import org.openecomp.sdc.be.config.BeEcompErrorManager;
48 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
49 import org.openecomp.sdc.be.dao.api.ActionStatus;
50 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
51 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
52 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
53 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
54 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
55 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
56 import org.openecomp.sdc.be.info.ArtifactDefinitionInfo;
57 import org.openecomp.sdc.be.info.ArtifactTemplateInfo;
58 import org.openecomp.sdc.be.info.GroupDefinitionInfo;
59 import org.openecomp.sdc.be.model.ArtifactDefinition;
60 import org.openecomp.sdc.be.model.Component;
61 import org.openecomp.sdc.be.model.ComponentInstance;
62 import org.openecomp.sdc.be.model.ComponentParametersView;
63 import org.openecomp.sdc.be.model.DataTypeDefinition;
64 import org.openecomp.sdc.be.model.GroupDefinition;
65 import org.openecomp.sdc.be.model.GroupInstance;
66 import org.openecomp.sdc.be.model.GroupInstanceProperty;
67 import org.openecomp.sdc.be.model.GroupProperty;
68 import org.openecomp.sdc.be.model.GroupTypeDefinition;
69 import org.openecomp.sdc.be.model.PropertyDefinition;
70 import org.openecomp.sdc.be.model.PropertyDefinition.GroupInstancePropertyValueUpdateBehavior;
71 import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames;
72 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
73 import org.openecomp.sdc.be.model.jsontitan.operations.ArtifactsOperations;
74 import org.openecomp.sdc.be.model.jsontitan.operations.GroupsOperation;
75 import org.openecomp.sdc.be.model.Resource;
76 import org.openecomp.sdc.be.model.User;
77 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
78 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
79 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
80 import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
81 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
82 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
83 import org.openecomp.sdc.common.api.Constants;
84 import org.openecomp.sdc.exception.ResponseFormat;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87 import org.springframework.beans.factory.annotation.Autowired;
88
89 import com.google.gson.Gson;
90 import com.google.gson.GsonBuilder;
91 import com.google.gson.JsonSyntaxException;
92
93 import fj.data.Either;
94
95 @org.springframework.stereotype.Component("groupBusinessLogic")
96 public class GroupBusinessLogic extends BaseBusinessLogic {
97         private static String ADDING_GROUP = "AddingGroup";
98
99         public static final String INITIAL_VERSION = "1";
100
101         private static final String CREATE_GROUP = "CreateGroup";
102
103         private static final String UPDATE_GROUP = "UpdateGroup";
104
105         private static final String GET_GROUP = "GetGroup";
106
107         private static Logger log = LoggerFactory.getLogger(GroupBusinessLogic.class.getName());
108
109         public GroupBusinessLogic() {
110
111         }
112
113         @javax.annotation.Resource
114         private GroupTypeOperation groupTypeOperation;
115
116         @Autowired
117         ArtifactsOperations artifactsOperation;
118
119         @Autowired
120         private GroupsOperation groupsOperation;
121         @Autowired
122         private ApplicationDataTypeCache dataTypeCache;
123
124         /**
125          * 
126          * 1. validate user exist
127          * 
128          * 2. validate component can be edited
129          * 
130          * 3. verify group not already exist
131          * 
132          * 4. verify type of group exist
133          * 
134          * 5. verify Component instances exist under the component
135          * 
136          * 6. verify the component instances type are allowed according to the member types in the group type
137          * 
138          * 7. verify the artifacts belongs to the component
139          * 
140          * @param componentId
141          * @param userId
142          * @param componentType
143          * @param groupDefinition
144          * @param inTransaction
145          * @return
146          */
147         /*
148          * public Either<GroupDefinition, ResponseFormat> createGroup(String componentId, String userId, ComponentTypeEnum componentType, GroupDefinition groupDefinition, boolean inTransaction) {
149          * 
150          * Either<GroupDefinition, ResponseFormat> result = null;
151          * 
152          * try { Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, CREATE_GROUP, inTransaction);
153          * 
154          * if (validateUserExists.isRight()) { result = Either.right(validateUserExists.right().value()); return result; }
155          * 
156          * User user = validateUserExists.left().value(); // 5. check service/resource existence // 6. check service/resource check out // 7. user is owner of checkout state org.openecomp.sdc.be.model.Component component = null;
157          * 
158          * // String realComponentId = componentType == // ComponentTypeEnum.RESOURCE_INSTANCE ? parentId : componentId; String realComponentId = componentId;
159          * 
160          * ComponentParametersView componentParametersView = new ComponentParametersView(); componentParametersView.disableAll(); componentParametersView.setIgnoreGroups(false); componentParametersView.setIgnoreArtifacts(false);
161          * componentParametersView.setIgnoreUsers(false); componentParametersView.setIgnoreComponentInstances(false);
162          * 
163          * Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
164          * 
165          * if (validateComponent.isRight()) { result = Either.right(validateComponent.right().value()); return result; } component = validateComponent.left().value(); Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component,
166          * userId); if (canWork.isRight()) { result = Either.right(canWork.right().value()); return result; }
167          * 
168          * result = this.createGroup(component, user, componentType, groupDefinition, inTransaction); return result;
169          * 
170          * } finally {
171          * 
172          * if (false == inTransaction) {
173          * 
174          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
175          * 
176          * }
177          * 
178          * } }
179          */
180
181         private String getComponentTypeForResponse(org.openecomp.sdc.be.model.Component component) {
182                 String componentTypeForResponse = "SERVICE";
183                 if (component instanceof Resource) {
184                         componentTypeForResponse = ((Resource) component).getResourceType().name();
185                 }
186                 return componentTypeForResponse;
187         }
188
189         /**
190          * Verify that the artifact members belongs to the component
191          * 
192          * @param component
193          * @param artifacts
194          * @return
195          */
196         private Either<Boolean, ResponseFormat> verifyArtifactsBelongsToComponent(Component component, List<String> artifacts, String context) {
197
198                 if (artifacts == null || true == artifacts.isEmpty()) {
199                         return Either.left(true);
200                 }
201
202                 Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
203                 if (deploymentArtifacts == null || true == deploymentArtifacts.isEmpty()) {
204                         BeEcompErrorManager.getInstance().logInvalidInputError(context, "No deployment artifact found under component " + component.getNormalizedName(), ErrorSeverity.INFO);
205                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
206                 }
207
208                 List<String> currentArtifacts = deploymentArtifacts.values().stream().map(p -> p.getUniqueId()).collect(Collectors.toList());
209                 log.debug("The deployment artifacts of component {} are {}", component.getNormalizedName(), deploymentArtifacts);
210                 if (false == currentArtifacts.containsAll(artifacts)) {
211                         BeEcompErrorManager.getInstance().logInvalidInputError(context, "Not all artifacts belongs to component " + component.getNormalizedName(), ErrorSeverity.INFO);
212                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
213                 }
214
215                 return Either.left(true);
216
217         }
218
219         /**
220          * verify that the members are component instances of the component
221          * 
222          * @param component
223          * @param componentType
224          * @param groupMembers
225          * @param memberToscaTypes
226          * @return
227          */
228         private Either<Boolean, ResponseFormat> verifyComponentInstancesAreValidMembers(Component component, ComponentTypeEnum componentType, String groupName, String groupType, Map<String, String> groupMembers, List<String> memberToscaTypes) {
229
230                 if (groupMembers == null || true == groupMembers.isEmpty()) {
231                         return Either.left(true);
232                 }
233
234                 if (memberToscaTypes == null || true == memberToscaTypes.isEmpty()) {
235                         return Either.left(true);
236                 }
237
238                 List<ComponentInstance> componentInstances = component.getComponentInstances();
239                 if (componentInstances != null && false == componentInstances.isEmpty()) {
240                         Map<String, ComponentInstance> compInstUidToCompInstMap = componentInstances.stream().collect(Collectors.toMap(p -> p.getUniqueId(), p -> p));
241
242                         Set<String> allCompInstances = compInstUidToCompInstMap.keySet();
243
244                         for (Entry<String, String> groupMember : groupMembers.entrySet()) {
245                                 String compName = groupMember.getKey();
246                                 String compUid = groupMember.getValue();
247
248                                 if (false == allCompInstances.contains(compUid)) {
249                                         /*
250                                          * %1 - member name %2 - group name %3 - VF name %4 - component type [VF ]
251                                          */
252                                         String componentTypeForResponse = getComponentTypeForResponse(component);
253
254                                         BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "Not all group members exists under the component", ErrorSeverity.INFO);
255                                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, compName, groupName, component.getNormalizedName(), componentTypeForResponse));
256                                 }
257                         }
258
259                         // ComponentOperation componentOperation = getComponentOperationByParentComponentType(componentType);
260                         // if (componentOperation instanceof ResourceOperation) {
261                         // ResourceOperation resourceOperation = (ResourceOperation) componentOperation;
262                         //
263                         // for (Entry<String, String> groupMember : groupMembers.entrySet()) {
264                         //
265                         // String componentInstName = groupMember.getKey();
266                         // String componentInstUid = groupMember.getValue();
267                         //
268                         // ComponentInstance componentInstance = compInstUidToCompInstMap.get(componentInstUid);
269                         // String componentUid = componentInstance.getComponentUid();
270                         // List<String> componentToscaNames = new ArrayList<>();
271                         // TitanOperationStatus status = resourceOperation.fillResourceDerivedListFromGraph(componentUid, componentToscaNames);
272                         // if (status != TitanOperationStatus.OK) {
273                         // BeEcompErrorManager.getInstance().logInternalFlowError(CREATE_GROUP, "Cannot find tosca list of component id " + componentUid, ErrorSeverity.ERROR);
274                         // return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
275                         // }
276                         //
277                         // log.debug("The tosca names of component id {} are {}", componentUid, memberToscaTypes);
278                         //
279                         // boolean found = false;
280                         // for (String memberToscaType : memberToscaTypes) {
281                         // if (componentToscaNames.contains(memberToscaType)) {
282                         // found = true;
283                         // break;
284                         // }
285                         // }
286                         // if (found == false) {
287                         // BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP,
288                         // "No tosca types from " + memberToscaTypes + " can be found in the tosca list " + componentToscaNames + " of component " + componentInstance.getNormalizedName(), ErrorSeverity.INFO);
289                         // /*
290                         // * # %1 - member name # %2 - group name # %3 - group type
291                         // */
292                         // return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_INVALID_TOSCA_NAME_OF_COMPONENT_INSTANCE, componentInstName, groupName, groupType));
293                         // } else {
294                         // log.debug("Component instance {} fits to one of the required tosca types", componentInstance.getNormalizedName());
295                         // }
296                         // }
297                         // } else {
298                         // BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "Cannot find tosca list since it is not supported for product", ErrorSeverity.ERROR);
299                         // return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
300                         // }
301
302                 }
303
304                 return Either.left(true);
305         }
306
307         /**
308          * Update specific group version
309          * 
310          * @param groupDefinition
311          * @param inTransaction
312          * @return
313          */
314         /*
315          * public Either<GroupDefinition, StorageOperationStatus> updateGroupVersion(GroupDefinition groupDefinition, boolean inTransaction) { Either<GroupDefinition, StorageOperationStatus> result = null; List<String> groupIdsToUpdateVersion = new
316          * ArrayList<>(); groupIdsToUpdateVersion.add(groupDefinition.getUniqueId()); Either<List<GroupDefinition>, StorageOperationStatus> updateGroupVersion = updateGroupVersion(groupIdsToUpdateVersion, inTransaction); if (updateGroupVersion.isLeft())
317          * { result = Either.left(updateGroupVersion.left().value().get(0)); } else { log.debug("Failed to update group version. Status is {} ", updateGroupVersion.right().value()); result = Either.right(updateGroupVersion.right().value()); } return
318          * result; }
319          */
320
321         /**
322          * Update list of groups versions
323          * 
324          * @param groupsUniqueId
325          * @param inTransaction
326          * @return
327          */
328         /*
329          * public Either<List<GroupDefinition>, StorageOperationStatus> updateGroupVersion(List<String> groupsUniqueId, boolean inTransaction) {
330          * 
331          * Either<List<GroupDefinition>, StorageOperationStatus> result = null;
332          * 
333          * try {
334          * 
335          * result = groupOperation.updateGroupVersion(groupsUniqueId, true);
336          * 
337          * return result;
338          * 
339          * } finally {
340          * 
341          * if (false == inTransaction) {
342          * 
343          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
344          * 
345          * }
346          * 
347          * }
348          * 
349          * }
350          */
351
352         /**
353          * Update GroupDefinition metadata
354          * 
355          * @param componentId
356          * @param user
357          * @param componentType
358          * @param updatedGroup
359          * @param inTransaction
360          * @return
361          */
362         public Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(String componentId, User user, ComponentTypeEnum componentType, GroupDefinition updatedGroup, boolean inTransaction , boolean shouldLock) {
363
364                 Either<GroupDefinition, ResponseFormat> result = null;
365                 try {
366                         // Validate user exist
367                         Either<User, ResponseFormat> validateUserExists = validateUserExists(user.getUserId(), UPDATE_GROUP, inTransaction);
368                         if (validateUserExists.isRight()) {
369                                 result = Either.right(validateUserExists.right().value());
370                                 return result;
371                         }
372                         // Validate component exist
373                         Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(componentId, componentType, null);
374                         if (validateComponent.isRight()) {
375                                 result = Either.right(validateComponent.right().value());
376                                 return result;
377                         }
378                         org.openecomp.sdc.be.model.Component component = validateComponent.left().value();
379                         // validate we can work on component
380                         Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, user.getUserId());
381                         if (canWork.isRight()) {
382                                 result = Either.right(canWork.right().value());
383                                 return result;
384                         }
385                         List<GroupDefinition> currentGroups = component.getGroups();
386                         if (CollectionUtils.isEmpty(currentGroups)) {
387                                 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(), component.getName(), ActionStatus.GROUP_IS_MISSING);
388                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(), component.getComponentType().getValue()));
389                                 return result;
390                         }
391                         // Validate groups exists in the component
392                         Optional<GroupDefinition> currentGroupOpt = currentGroups.stream().filter(g -> g.getUniqueId().equals(updatedGroup.getUniqueId())).findAny();
393                         if (!currentGroupOpt.isPresent()) {
394                                 log.error("Failed to update the metadata of group {} on component {}. The status is {}. ", updatedGroup.getName(), component.getName(), ActionStatus.GROUP_IS_MISSING);
395                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, updatedGroup.getName(), component.getName(), component.getComponentType().getValue()));
396                                 return result;
397                         }
398                         GroupDefinition currentGroup = currentGroupOpt.get();
399                         if ( shouldLock ){
400                                 Either<Boolean, ResponseFormat> lockResult = lockComponent(componentId, component, "Update GroupDefinition Metadata");
401                                 if (lockResult.isRight()) {
402                                         result = Either.right(lockResult.right().value());
403                                         return result;
404                                 }
405                         }
406                         // Validate group type is vfModule
407                         if (!currentGroup.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
408                                 log.error("Failed to update the metadata of group {}. Group type is {} and different then: {}", currentGroup.getName(), currentGroup.getType(), Constants.DEFAULT_GROUP_VF_MODULE);
409                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_TYPE, updatedGroup.getType());
410                                 result = Either.right(responseFormat);
411                                 return result;
412                         }
413                         result = updateGroupMetadata(component, currentGroup, updatedGroup);
414                         return result;
415
416                 } finally {
417                         if (result.isLeft()) {
418                                 titanDao.commit();
419                         } else {
420                                 titanDao.rollback();
421                         }
422                         if( shouldLock )
423                                 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
424                 }
425         }
426
427         private Either<GroupDefinition, ResponseFormat> updateGroupMetadata(Component component, GroupDefinition currentGroup, GroupDefinition updatedGroup) {
428                 String currentGroupName = currentGroup.getName();
429                 Either<GroupDefinition, ResponseFormat> result = validateAndUpdateGroupMetadata(currentGroup, updatedGroup);
430
431                 if (result.isRight()) {
432                         log.debug("Failed to validate a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
433                 }
434                 if (result.isLeft()) {
435                         result = updateGroup(component, currentGroup, currentGroupName);
436                 }
437                 return result;
438         }
439
440         private Either<GroupDefinition, ResponseFormat> updateGroup(Component component, GroupDefinition updatedGroup, String currentGroupName) {
441                 Either<GroupDefinition, StorageOperationStatus> handleGroupRes;
442                 Either<GroupDefinition, ResponseFormat> result = null;
443                 if (updatedGroup.getName().equals(currentGroupName)) {
444                         handleGroupRes = groupsOperation.updateGroup(component, updatedGroup);
445                         if (handleGroupRes.isRight()) {
446                                 log.debug("Failed to update a metadata of the group {} on component {}. ", updatedGroup.getName(), component.getName());
447                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(handleGroupRes.right().value())));
448                         }
449                 } else {
450                         StorageOperationStatus deleteStatus = groupsOperation.deleteGroup(component, currentGroupName);
451                         if (deleteStatus != StorageOperationStatus.OK) {
452                                 log.debug("Failed to delete the group {} from component {}. ", updatedGroup.getName(), component.getName());
453                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteStatus)));
454                         }
455                         handleGroupRes = groupsOperation.addGroup(component, updatedGroup);
456                         if (handleGroupRes.isRight()) {
457                                 log.debug("Failed to add the group {} to component {}. ", updatedGroup.getName(), component.getName());
458                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(handleGroupRes.right().value())));
459                         }
460                 }
461                 if (result == null) {
462                         result = Either.left(updatedGroup);
463                 }
464                 return result;
465         }
466
467         /**
468          * Validate and Update Group Property
469          * 
470          * @param componentId
471          * @param groupUniqueId
472          * @param user
473          * @param componentType
474          * @param groupPropertiesToUpdate
475          * @param inTransaction
476          * @return
477          */
478         public Either<List<GroupProperty>, ResponseFormat> validateAndUpdateGroupProperties(String componentId, String groupUniqueId, User user, ComponentTypeEnum componentType, List<GroupProperty> groupPropertiesToUpdate, boolean inTransaction) {
479
480                 Either<List<GroupProperty>, ResponseFormat> result = Either.left(groupPropertiesToUpdate);
481                 try {
482                         Optional<GroupDefinition> optionalGroupConnectedToVf = null;
483                         GroupDefinition currentGroup = null;
484                         StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, componentType.getNodeType());
485                         if (lockResult != StorageOperationStatus.OK) {
486                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockResult, componentType), componentId));
487                         }
488                         if (result.isLeft()) {
489                                 // VF exist because lock succedded
490                                 Resource vf = (Resource) toscaOperationFacade.getToscaElement(componentId).left().value();
491                                 optionalGroupConnectedToVf =
492                                                 // All groups on resource
493                                                 vf.getGroups().stream().
494                                                 // Filter in group sent is part of VF groups
495                                                                 filter(e -> e.getUniqueId().equals(groupUniqueId)).
496                                                                 // Collect
497                                                                 findAny();
498                                 if (!optionalGroupConnectedToVf.isPresent()) {
499                                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, groupUniqueId, vf.getName(), ComponentTypeEnum.RESOURCE.getValue()));
500                                 }
501                         }
502
503                         if (result.isLeft()) {
504                                 currentGroup = optionalGroupConnectedToVf.get();
505                                 result = validateGroupPropertyAndResetEmptyValue(currentGroup, groupPropertiesToUpdate);
506                         }
507                         if (result.isLeft()) {
508                                 result = updateGroupPropertiesValue(componentId, currentGroup, groupPropertiesToUpdate, inTransaction);
509                                 if (result.isRight()) {
510                                         BeEcompErrorManager.getInstance().logBeSystemError("Update GroupProperties");
511                                         log.debug("failed to update Vf {}", componentId);
512                                 }
513                         }
514
515                 } catch (Exception e) {
516                         log.debug("Error in validateAndUpdateGroupProperty {}", e);
517                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
518                 } finally {
519                         graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
520                 }
521                 return result;
522         }
523
524         private void resetEmptyValueWithDefaults(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
525                 Map<String, GroupProperty> originalProperties =
526                                 // Stream of original properties from group
527                                 originalGroup.convertToGroupProperties().stream().
528                                 // Collecting to map with name as key
529                                                 collect(Collectors.toMap(e -> e.getName(), e -> e));
530                 for (GroupProperty gp : groupPropertiesToUpdate) {
531                         if (StringUtils.isEmpty(gp.getValue())) {
532                                 gp.setValue(originalProperties.get(gp.getName()).getDefaultValue());
533                         }
534                 }
535
536         }
537
538         private Either<List<GroupProperty>, ResponseFormat> validateGroupPropertyAndResetEmptyValue(GroupDefinition originalGroup, List<GroupProperty> groupPropertiesToUpdate) {
539
540                 Either<List<GroupProperty>, ResponseFormat> ret = validateOnlyValueChanged(groupPropertiesToUpdate, originalGroup);
541                 if (ret.isLeft()) {
542                         resetEmptyValueWithDefaults(groupPropertiesToUpdate, originalGroup);
543                 }
544                 if (ret.isLeft()) {
545                         // Validate Type Match Value
546                         Optional<StorageOperationStatus> optionalError =
547                                         // Stream of group properties
548                                         groupPropertiesToUpdate.stream().
549                                         // Validate each and map to returned Strorage status value
550                                                         map(e -> groupOperation.validateAndUpdatePropertyValue(e)).
551                                                         // Keep only failed result if there is such
552                                                         filter(e -> e != StorageOperationStatus.OK).
553                                                         // collect
554                                                         findFirst();
555                         if (optionalError.isPresent()) {
556                                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(optionalError.get());
557                                 ret = Either.right(componentsUtils.getResponseFormat(actionStatus));
558                         }
559
560                 }
561                 if (ret.isLeft()) {
562                         // Validate min max ect...
563                         ret = validatePropertyBusinessLogic(groupPropertiesToUpdate, originalGroup);
564                 }
565
566                 return ret;
567         }
568
569         private Either<List<GroupProperty>, ResponseFormat> validatePropertyBusinessLogic(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
570
571                 Either<List<GroupProperty>, ResponseFormat> ret = Either.left(groupPropertiesToUpdate);
572
573                 Map<PropertyNames, String> nameValueMap = new HashMap<>();
574                 for (GroupProperty gp : groupPropertiesToUpdate) {
575                         // Filter out non special properties which does not have Enum
576                         final PropertyNames gpEnum = PropertyNames.findName(gp.getName());
577                         if (gpEnum != null) {
578                                 nameValueMap.put(gpEnum, gp.getValue());
579                         }
580                 }
581
582                 if (!MapUtils.isEmpty(nameValueMap)) {
583
584                         if (nameValueMap.containsKey(PropertyNames.INITIAL_COUNT) || nameValueMap.containsKey(PropertyNames.MAX_INSTANCES) || nameValueMap.containsKey(PropertyNames.MIN_INSTANCES)) {
585
586                                 Map<PropertyNames, String> oldValueMap = prepareMapWithOriginalProperties(originalGroup);
587
588                                 Either<Boolean, ResponseFormat> eitherValid = validateMinMaxAndInitialCountPropertyLogicVF(nameValueMap, oldValueMap);
589                                 if (eitherValid.isRight()) {
590                                         ret = Either.right(eitherValid.right().value());
591                                 }
592                         }
593                         if (ret.isLeft() && (nameValueMap.containsKey(PropertyNames.VF_MODULE_DESCRIPTION) || nameValueMap.containsKey(PropertyNames.VF_MODULE_LABEL))) {
594
595                                 Optional<ResponseFormat> optionalError =
596                                                 // Stream of group Properties
597                                                 groupPropertiesToUpdate.stream().
598                                                 // Filter in only properties that needs text validation
599                                                                 filter(e -> enumHasValueFilter(e.getName(), enumName -> PropertyNames.findName(enumName), PropertyNames.VF_MODULE_DESCRIPTION, PropertyNames.VF_MODULE_LABEL)).
600                                                                 // validate text properties
601                                                                 map(e -> validateFreeText(e)).
602                                                                 // filter in only errors if exist
603                                                                 filter(e -> e.isRight()).
604                                                                 // map the Either value to the Error
605                                                                 map(e -> e.right().value())
606                                                                 // collect
607                                                                 .findFirst();
608                                 if (optionalError.isPresent()) {
609                                         ret = Either.right(optionalError.get());
610                                 }
611
612                         }
613                 }
614
615                 return ret;
616         }
617
618         private Map<PropertyNames, String> prepareMapWithOriginalProperties(GroupDefinition originalGroup) {
619                 Map<PropertyNames, String> oldValueMap = new HashMap<>();
620                 PropertyNames[] propertiesToCheck = new PropertyNames[] { PropertyNames.INITIAL_COUNT, PropertyNames.MAX_INSTANCES, PropertyNames.MIN_INSTANCES };
621
622                 for (GroupProperty gp : originalGroup.convertToGroupProperties()) {
623                         if (enumHasValueFilter(gp.getName(), enumName -> PropertyNames.findName(enumName), propertiesToCheck)) {
624                                 oldValueMap.put(PropertyNames.findName(gp.getName()), gp.getValue());
625                         }
626                 }
627                 if (StringUtils.isEmpty(oldValueMap.get(PropertyNames.MAX_INSTANCES))) {
628                         oldValueMap.put(PropertyNames.MAX_INSTANCES, String.valueOf(Integer.MAX_VALUE));
629                 }
630                 return oldValueMap;
631         }
632
633         private Either<List<GroupProperty>, ResponseFormat> validateOnlyValueChanged(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
634
635                 Either<List<GroupProperty>, ResponseFormat> ret = Either.left(groupPropertiesToUpdate);
636                 if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) {
637                         ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY));
638                 } else if (CollectionUtils.isEmpty(originalGroup.getProperties())) {
639                         ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, groupPropertiesToUpdate.get(NumberUtils.INTEGER_ZERO).getName()));
640                 } else {
641                         Map<String, GroupProperty> namePropertyMap =
642                                         // Original Group Properties Stream
643                                         originalGroup.convertToGroupProperties().stream().
644                                         // Collect to map with name as key
645                                                         collect(Collectors.toMap(e -> e.getName(), e -> e));
646
647                         Optional<GroupProperty> optionalMissingProperty =
648                                         // Group Properties to be updated Stream
649                                         groupPropertiesToUpdate.stream().
650                                         // Filter in property that is not contained in original if there is such
651                                                         filter(e -> !namePropertyMap.containsKey(e.getName())).
652                                                         // collect
653                                                         findFirst();
654
655                         if (optionalMissingProperty.isPresent()) {
656                                 ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, optionalMissingProperty.get().getName()));
657                         } else {
658                                 Optional<GroupProperty> optionalNonValueChange =
659                                                 // groups to be updated stream
660                                                 groupPropertiesToUpdate.stream().
661                                                 // filter in only properties with non-value (illegal) change
662                                                                 filter(e -> !isOnlyGroupPropertyValueChanged(e, namePropertyMap.get(e.getName()))).
663                                                                 // Collect
664                                                                 findFirst();
665                                 if (optionalNonValueChange.isPresent()) {
666                                         ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY, optionalNonValueChange.get().getName()));
667
668                                 }
669                         }
670
671                 }
672                 return ret;
673         }
674
675         /**
676          * if groupProperty are the same or if only value is different returns true, otherwise returns false.
677          * 
678          * @param groupProperty
679          * @param groupProperty2
680          * @return
681          */
682         private boolean isOnlyGroupPropertyValueChanged(GroupProperty groupProperty, GroupProperty groupProperty2) {
683                 // Create 2 duplicates for groupPropery and reset their values
684                 Gson gson = new GsonBuilder().setPrettyPrinting().create();
685                 try {
686                         GroupProperty groupPropertyDuplicate = new GroupProperty(groupProperty);
687                         groupPropertyDuplicate.setValue(null);
688                         groupPropertyDuplicate.setSchema(null);
689                         groupPropertyDuplicate.setParentUniqueId(null);
690                         // GroupProperty groupProperty2Duplicate = gson.fromJson(JsonParserUtils.jsonToString(groupProperty2), GroupProperty.class);
691                         GroupProperty groupProperty2Duplicate = new GroupProperty(groupProperty2);
692                         groupProperty2Duplicate.setValue(null);
693                         groupProperty2Duplicate.setSchema(null);
694                         groupProperty2Duplicate.setParentUniqueId(null);
695                         return groupPropertyDuplicate.equals(groupProperty2Duplicate) && StringUtils.equals(groupPropertyDuplicate.getValueUniqueUid(), groupProperty2Duplicate.getValueUniqueUid());
696                 } catch (Exception e) {
697                         log.debug("Failed validate group properties. ", e);
698                         return false;
699                 }
700         }
701
702         /**
703          * Validate and update GroupDefinition metadata
704          * 
705          * @param user
706          * @param currentGroup
707          * @param groupUpdate
708          * @return
709          **/
710         private Either<GroupDefinition, ResponseFormat> validateAndUpdateGroupMetadata(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
711                 // Check if to update, and update GroupDefinition name.
712                 Either<Boolean, ResponseFormat> response = validateAndUpdateGroupName(currentGroup, groupUpdate);
713                 if (response.isRight()) {
714                         ResponseFormat errorResponse = response.right().value();
715                         return Either.right(errorResponse);
716                 }
717
718                 // Do not allow to update GroupDefinition version directly.
719                 String versionUpdated = groupUpdate.getVersion();
720                 String versionCurrent = currentGroup.getVersion();
721                 if (versionUpdated != null && !versionCurrent.equals(versionUpdated)) {
722                         log.info("update Group: recived request to update version to {} the field is not updatable ignoring.", versionUpdated);
723                 }
724
725                 return Either.left(currentGroup);
726         }
727
728         /**
729          * Validate and update GroupDefinition name
730          * 
731          * @param user
732          * @param currentGroup
733          * @param groupUpdate
734          * @return
735          */
736         private Either<Boolean, ResponseFormat> validateAndUpdateGroupName(GroupDefinition currentGroup, GroupDefinition groupUpdate) {
737                 String nameUpdated = groupUpdate.getName();
738                 String nameCurrent = currentGroup.getName();
739                 if (!nameCurrent.equals(nameUpdated)) {
740                         Either<Boolean, ResponseFormat> validatNameResponse = validateGroupName(currentGroup.getName(), groupUpdate.getName() ,true);
741                         if (validatNameResponse.isRight()) {
742                                 ResponseFormat errorRespons = validatNameResponse.right().value();
743                                 return Either.right(errorRespons);
744                         }
745                         currentGroup.setName(groupUpdate.getName());
746                 }
747                 return Either.left(true);
748         }
749
750         /**
751          * 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
752          * MyDesc was changed.
753          * 
754          * @param currentGroupName
755          * @param groupUpdateName
756          * @return
757          */
758         private Either<Boolean, ResponseFormat> validateGroupName(String currentGroupName, String groupUpdateName , boolean isforceNameModification) {
759                 try {
760                         // Check if the group name is in old format.
761                         if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupUpdateName).matches()) {
762                                 log.error("Group name {} is in old format", groupUpdateName);
763                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME, groupUpdateName));
764                         }
765
766                         // Check that name pats 1 and 3 did not changed (only the second
767                         // part can be changed)
768                         // But verify before that the current group format is the new one
769                         if (!Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(currentGroupName).matches()) {
770                                 String[] split1 = currentGroupName.split("\\.\\.");
771                                 String currentResourceName = split1[0];
772                                 String currentCounter = split1[2];
773
774                                 String[] split2 = groupUpdateName.split("\\.\\.");
775                                 String groupUpdateResourceName = split2[0];
776                                 String groupUpdateCounter = split2[2];
777                                 if (!isforceNameModification){                  //if not forced ,allow name prefix&suffix validation [no changes]
778                                         if (!currentResourceName.equals(groupUpdateResourceName)) {
779                                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentResourceName));
780                                         }
781
782                                         if (!currentCounter.equals(groupUpdateCounter)) {
783                                                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentCounter));
784                                         }
785                                 }
786
787                         }
788
789                         return Either.left(true);
790                 } catch (Exception e) {
791                         log.error("Error valiadting group name", e);
792                         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
793                 }
794         }
795
796         /**
797          * associate artifacts to a given group
798          * 
799          * @param componentId
800          * @param userId
801          * @param componentType
802          * @param groups
803          * @param shouldLockComp
804          * @param inTransaction
805          * @return
806          */
807         /*
808          * public Either<List<GroupDefinition>, ResponseFormat> associateArtifactsToGroup(String componentId, String userId, ComponentTypeEnum componentType, List<GroupDefinition> groups, boolean shouldLockComp, boolean inTransaction) {
809          * 
810          * Either<List<GroupDefinition>, ResponseFormat> result = null;
811          * 
812          * if (shouldLockComp == true && inTransaction == true) { BeEcompErrorManager.getInstance().logInternalFlowError("dissociateArtifactsFromGroup", "Cannot lock component since we are inside a transaction", ErrorSeverity.ERROR); // Cannot lock
813          * component since we are in a middle of another // transaction. ActionStatus actionStatus = ActionStatus.INVALID_CONTENT; result = Either.right(componentsUtils.getResponseFormat(actionStatus)); return result; }
814          * 
815          * Component component = null; try {
816          * 
817          * if (groups == null || groups.isEmpty()) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.OK)); }
818          * 
819          * Either<Component, ResponseFormat> validateGroupsBeforeUpdate = validateGroupsBeforeUpdate(componentId, userId, componentType, groups, inTransaction); if (validateGroupsBeforeUpdate.isRight()) { result =
820          * Either.right(validateGroupsBeforeUpdate.right().value()); return result; }
821          * 
822          * component = validateGroupsBeforeUpdate.left().value();
823          * 
824          * if (shouldLockComp) { Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, "Group - Associate Artifacts"); if (lockComponent.isRight()) { return Either.right(lockComponent.right().value()); } }
825          * 
826          * List<GroupDefinition> updatedGroups = new ArrayList<>();
827          * 
828          * List<GroupDefinition> componentGroups = component.getGroups();
829          * 
830          * // per group, associate to it the artifacts for (GroupDefinition groupDefinition : groups) {
831          * 
832          * GroupDefinition componentGroup = componentGroups.stream().filter(p -> p.getUniqueId().equals(groupDefinition.getUniqueId())).findFirst().orElse(null); if (componentGroup != null) { List<String> componentArtifacts =
833          * componentGroup.getArtifacts(); int artifactsSizeInGroup = componentArtifacts == null ? 0 : componentArtifacts.size(); if (artifactsSizeInGroup > 0) { List<String> artifactsToAssociate = groupDefinition.getArtifacts();
834          * 
835          * // if no artifcats sent if (artifactsToAssociate == null || true == artifactsToAssociate.isEmpty()) { continue; }
836          * 
837          * boolean isChanged = componentArtifacts.removeAll(artifactsToAssociate); if (isChanged) {// I.e. At least one artifact is already // associated to the group log.debug("Some of the artifacts already associated to group {}" ,
838          * groupDefinition.getUniqueId()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ARTIFACT_ALREADY_ASSOCIATED, componentGroup.getName())); } } }
839          * 
840          * Either<GroupDefinition, StorageOperationStatus> associateArtifactsToGroup = groupOperation.associateArtifactsToGroup(groupDefinition.getUniqueId(), groupDefinition.getArtifacts(), true);
841          * 
842          * if (associateArtifactsToGroup.isRight()) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(associateArtifactsToGroup.right().value()); result = Either.right(componentsUtils.getResponseFormat(actionStatus));
843          * log.debug("Failed to update group {} under component {}, error: {}", groupDefinition.getName(), component.getNormalizedName(), actionStatus.name()); return result; } updatedGroups.add(associateArtifactsToGroup.left().value());
844          * 
845          * }
846          * 
847          * result = Either.left(updatedGroups); return result;
848          * 
849          * } finally {
850          * 
851          * if (false == inTransaction) {
852          * 
853          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
854          * 
855          * }
856          * 
857          * // unlock resource if (shouldLockComp && component != null) { graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); }
858          * 
859          * } }
860          */
861
862         /*
863          * public Either<List<GroupDefinition>, ResponseFormat> associateMembersToGroup(String componentId, String userId, ComponentTypeEnum componentType, List<GroupDefinition> groups, boolean shouldLockComp, boolean inTransaction) {
864          * 
865          * Either<List<GroupDefinition>, ResponseFormat> result = null;
866          * 
867          * if (shouldLockComp == true && inTransaction == true) { BeEcompErrorManager.getInstance().logInternalFlowError("dissociateArtifactsFromGroup", "Cannot lock component since we are inside a transaction", ErrorSeverity.ERROR); // Cannot lock
868          * component since we are in a middle of another // transaction. ActionStatus actionStatus = ActionStatus.INVALID_CONTENT; result = Either.right(componentsUtils.getResponseFormat(actionStatus)); return result; }
869          * 
870          * Component component = null; try {
871          * 
872          * if (groups == null || groups.isEmpty()) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.OK)); }
873          * 
874          * Either<Component, ResponseFormat> validateGroupsBeforeUpdate = validateGroupsBeforeUpdate(componentId, userId, componentType, groups, inTransaction); if (validateGroupsBeforeUpdate.isRight()) { result =
875          * Either.right(validateGroupsBeforeUpdate.right().value()); return result; }
876          * 
877          * component = validateGroupsBeforeUpdate.left().value();
878          * 
879          * if (shouldLockComp) { Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, "Group - Associate Members"); if (lockComponent.isRight()) { return Either.right(lockComponent.right().value()); } }
880          * 
881          * List<GroupDefinition> updatedGroups = new ArrayList<>();
882          * 
883          * // per group, associate to it the members for (GroupDefinition groupDefinition : groups) {
884          * 
885          * Either<GroupDefinition, StorageOperationStatus> associateMembersToGroup = groupOperation.associateMembersToGroup(groupDefinition.getUniqueId(), groupDefinition.getMembers(), true);
886          * 
887          * if (associateMembersToGroup.isRight()) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(associateMembersToGroup.right().value()); result = Either.right(componentsUtils.getResponseFormat(actionStatus));
888          * log.debug("Failed to update group {} under component {}, error: {}", groupDefinition.getName(), component.getNormalizedName(), actionStatus.name()); return result; } else { updatedGroups.add(associateMembersToGroup.left().value()); }
889          * 
890          * }
891          * 
892          * result = Either.left(updatedGroups); return result;
893          * 
894          * } finally {
895          * 
896          * if (false == inTransaction) {
897          * 
898          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
899          * 
900          * }
901          * 
902          * // unlock resource if (shouldLockComp && component != null) { graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); }
903          * 
904          * } }
905          */
906
907         /**
908          * associate artifacts to a given group
909          * 
910          * @param componentId
911          * @param userId
912          * @param componentType
913          * @param groups
914          * @param shouldLockComp
915          * @param inTransaction
916          * @return
917          */
918         public Either<GroupDefinitionInfo, ResponseFormat> getGroupWithArtifactsById(ComponentTypeEnum componentType, String componentId, String groupId, String userId, boolean inTransaction) {
919
920                 Either<GroupDefinitionInfo, ResponseFormat> result = null;
921
922                 // Validate user exist
923                 Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, UPDATE_GROUP, true);
924
925                 if (validateUserExists.isRight()) {
926                         result = Either.right(validateUserExists.right().value());
927                         return result;
928                 }
929
930                 // Validate component exist
931                 org.openecomp.sdc.be.model.Component component = null;
932                 String realComponentId = componentId;
933
934                 try {
935                         ComponentParametersView componentParametersView = new ComponentParametersView();
936                         componentParametersView.disableAll();
937                         componentParametersView.setIgnoreGroups(false);
938                         componentParametersView.setIgnoreArtifacts(false);
939                         componentParametersView.setIgnoreUsers(false);
940
941                         Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
942                         if (validateComponent.isRight()) {
943                                 result = Either.right(validateComponent.right().value());
944                                 return result;
945                         }
946                         component = validateComponent.left().value();
947
948                         Either<GroupDefinition, StorageOperationStatus> groupEither = findGroupOnComponent(component, groupId);
949
950                         if (groupEither.isRight()) {
951                                 log.debug("Faild to find group {} under component {}", groupId, component.getUniqueId());
952                                 BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "group  " + groupId + " not found under component " + component.getUniqueId(), ErrorSeverity.INFO);
953                                 String componentTypeForResponse = getComponentTypeForResponse(component);
954                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, groupId, component.getSystemName(), componentTypeForResponse));
955                                 return result;
956                         }
957                         GroupDefinition group = groupEither.left().value();
958
959                         Boolean isBase = null;// Constants.IS_BASE;
960                         List<GroupProperty> props = group.convertToGroupProperties();
961                         if (props != null && !props.isEmpty()) {
962                                 Optional<GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
963                                 if (isBasePropOp.isPresent()) {
964                                         GroupProperty propIsBase = isBasePropOp.get();
965                                         isBase = Boolean.parseBoolean(propIsBase.getValue());
966
967                                 } else {
968                                         BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
969                                         // return
970                                         // Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
971
972                                 }
973                         }
974
975                         List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
976                         List<ArtifactDefinition> artifactsFromComponent = new ArrayList<>();
977                         List<String> artifactsIds = group.getArtifacts();
978
979                         Map<String, ArtifactDefinition> deploymentArtifacts = null;
980                         if (MapUtils.isNotEmpty(component.getDeploymentArtifacts())) {
981                                 deploymentArtifacts = component.getDeploymentArtifacts().values().stream().collect(Collectors.toMap(a -> a.getUniqueId(), a -> a));
982                         }
983
984                         if (artifactsIds != null && !artifactsIds.isEmpty()) {
985                                 for (String id : artifactsIds) {
986                                         if (MapUtils.isEmpty(deploymentArtifacts) || !deploymentArtifacts.containsKey(id)) {
987                                                 log.debug("Failed to get artifact {} . Status is {} ", id, StorageOperationStatus.NOT_FOUND);
988                                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND));
989                                                 result = Either.right(responseFormat);
990                                                 return result;
991                                         }
992                                         artifactsFromComponent.add(deploymentArtifacts.get(id));
993                                 }
994                                 if (!artifactsFromComponent.isEmpty()) {
995                                         for (ArtifactDefinition artifactDefinition : artifactsFromComponent) {
996                                                 ArtifactDefinitionInfo artifactDefinitionInfo = new ArtifactDefinitionInfo(artifactDefinition);
997                                                 artifacts.add(artifactDefinitionInfo);
998                                         }
999                                 }
1000
1001                         }
1002                         GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
1003                         resultInfo.setIsBase(isBase);
1004                         if (!artifacts.isEmpty())
1005                                 resultInfo.setArtifacts(artifacts);
1006
1007                         result = Either.left(resultInfo);
1008
1009                         return result;
1010
1011                 } finally {
1012
1013                         if (false == inTransaction) {
1014
1015                                 if (result == null || result.isRight()) {
1016                                         log.debug("Going to execute rollback on create group.");
1017                                         titanDao.rollback();
1018                                 } else {
1019                                         log.debug("Going to execute commit on create group.");
1020                                         titanDao.commit();
1021                                 }
1022
1023                         }
1024
1025                 }
1026
1027         }
1028
1029         private Either<GroupDefinition, StorageOperationStatus> findGroupOnComponent(Component component, String groupId) {
1030
1031                 Either<GroupDefinition, StorageOperationStatus> result = null;
1032                 if (CollectionUtils.isNotEmpty(component.getGroups())) {
1033                         Optional<GroupDefinition> foundGroup = component.getGroups().stream().filter(g -> g.getUniqueId().equals(groupId)).findFirst();
1034                         if (foundGroup.isPresent()) {
1035                                 result = Either.left(foundGroup.get());
1036                         }
1037                 }
1038                 if (result == null) {
1039                         result = Either.right(StorageOperationStatus.NOT_FOUND);
1040                 }
1041                 return result;
1042         }
1043
1044         /**
1045          * @param componentId
1046          * @param userId
1047          * @param componentType
1048          * @param groups
1049          * @param inTransaction
1050          * @return
1051          */
1052         private Either<org.openecomp.sdc.be.model.Component, ResponseFormat> validateGroupsBeforeUpdate(String componentId, String userId, ComponentTypeEnum componentType, List<GroupDefinition> groups, boolean inTransaction) {
1053
1054                 Either<org.openecomp.sdc.be.model.Component, ResponseFormat> result;
1055
1056                 // Validate user exist
1057                 Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, UPDATE_GROUP, inTransaction);
1058                 if (validateUserExists.isRight()) {
1059                         result = Either.right(validateUserExists.right().value());
1060                         return result;
1061                 }
1062
1063                 // Validate component exist
1064                 String realComponentId = componentId;
1065
1066                 ComponentParametersView componentParametersView = new ComponentParametersView();
1067                 componentParametersView.disableAll();
1068                 componentParametersView.setIgnoreGroups(false);
1069                 componentParametersView.setIgnoreArtifacts(false);
1070                 componentParametersView.setIgnoreUsers(false);
1071                 componentParametersView.setIgnoreComponentInstances(false);
1072
1073                 Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
1074
1075                 if (validateComponent.isRight()) {
1076                         result = Either.right(validateComponent.right().value());
1077                         return result;
1078                 }
1079                 org.openecomp.sdc.be.model.Component component = validateComponent.left().value();
1080
1081                 // validate we can work on component
1082                 Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, userId);
1083                 if (canWork.isRight()) {
1084                         result = Either.right(canWork.right().value());
1085                         return result;
1086                 }
1087
1088                 // Validate groups exists in the component
1089                 ResponseFormat validateGroupsInComponent = validateGroupsInComponentByFunc(groups, component, p -> p.getUniqueId());
1090                 if (validateGroupsInComponent != null) {
1091                         result = Either.right(validateGroupsInComponent);
1092                         return result;
1093                 }
1094
1095                 Set<String> artifacts = new HashSet<>();
1096                 groups.forEach(p -> {
1097                         if (p.getArtifacts() != null) {
1098                                 artifacts.addAll(p.getArtifacts());
1099                         }
1100                 });
1101                 // validate all artifacts belongs to the component
1102                 Either<Boolean, ResponseFormat> verifyArtifactsBelongsToComponent = verifyArtifactsBelongsToComponent(component, new ArrayList<>(artifacts), UPDATE_GROUP);
1103                 if (verifyArtifactsBelongsToComponent.isRight()) {
1104                         result = Either.right(verifyArtifactsBelongsToComponent.right().value());
1105                         return result;
1106                 }
1107
1108                 return Either.left(component);
1109         }
1110
1111         /**
1112          * @param groups
1113          * @param component
1114          * @param getByParam
1115          *            - the method to fetch the key of the GroupDefinition(from groups) in order to compare to groups in the component
1116          * @return
1117          */
1118         private ResponseFormat validateGroupsInComponentByFunc(List<GroupDefinition> groups, org.openecomp.sdc.be.model.Component component, Function<GroupDefinition, String> getByParam) {
1119                 ResponseFormat result = null;
1120
1121                 List<GroupDefinition> currentGroups = component.getGroups();
1122
1123                 boolean found = false;
1124                 List<String> updatedGroupsName = groups.stream().map(getByParam).collect(Collectors.toList());
1125
1126                 List<String> missingGroupNames = updatedGroupsName;
1127
1128                 if (currentGroups != null && false == currentGroups.isEmpty()) {
1129                         List<String> currentGroupsName = currentGroups.stream().map(getByParam).collect(Collectors.toList());
1130
1131                         if (currentGroupsName.containsAll(updatedGroupsName)) {
1132                                 found = true;
1133                         } else {
1134                                 currentGroupsName.removeAll(currentGroupsName);
1135                                 missingGroupNames = currentGroupsName;
1136                         }
1137                 }
1138                 if (false == found) {
1139                         String componentTypeForResponse = getComponentTypeForResponse(component);
1140                         String listOfGroups = getAsString(missingGroupNames);
1141                         result = componentsUtils.getResponseFormat(ActionStatus.GROUP_IS_MISSING, listOfGroups, component.getSystemName(), componentTypeForResponse);
1142                         return result;
1143                 }
1144
1145                 return null;
1146         }
1147
1148         public String getAsString(List<String> list) {
1149
1150                 if (list == null || list.isEmpty()) {
1151                         return "";
1152                 }
1153                 StringBuilder builder = new StringBuilder();
1154                 list.forEach(p -> builder.append(p + ","));
1155
1156                 String result = builder.toString();
1157                 return result.substring(0, result.length());
1158
1159         }
1160
1161         /**
1162          * dissociate artifacts from a given group
1163          * 
1164          * @param componentId
1165          * @param userId
1166          * @param componentType
1167          * @param groups
1168          * @param shouldLockComp
1169          * @param inTransaction
1170          * @return
1171          */
1172         /*
1173          * public Either<List<GroupDefinition>, ResponseFormat> dissociateArtifactsFromGroup(String componentId, String userId, ComponentTypeEnum componentType, List<GroupDefinition> groups, boolean shouldLockComp, boolean inTransaction) {
1174          * 
1175          * Either<List<GroupDefinition>, ResponseFormat> result = null;
1176          * 
1177          * if (shouldLockComp == true && inTransaction == true) { BeEcompErrorManager.getInstance().logInternalFlowError("dissociateArtifactsFromGroup", "Cannot lock component since we are inside a transaction", ErrorSeverity.ERROR); // Cannot lock
1178          * component since we are in a middle of another // transaction. ActionStatus actionStatus = ActionStatus.INVALID_CONTENT; result = Either.right(componentsUtils.getResponseFormat(actionStatus)); return result; }
1179          * 
1180          * Component component = null;
1181          * 
1182          * try {
1183          * 
1184          * if (groups == null || groups.isEmpty()) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.OK)); }
1185          * 
1186          * Either<Component, ResponseFormat> validateGroupsBeforeUpdate = validateGroupsBeforeUpdate(componentId, userId, componentType, groups, inTransaction); if (validateGroupsBeforeUpdate.isRight()) { result =
1187          * Either.right(validateGroupsBeforeUpdate.right().value()); return result; }
1188          * 
1189          * component = validateGroupsBeforeUpdate.left().value();
1190          * 
1191          * if (shouldLockComp) { Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, "Group - Dissociate Artifacts"); if (lockComponent.isRight()) { return Either.right(lockComponent.right().value()); } }
1192          * 
1193          * List<GroupDefinition> updatedGroups = new ArrayList<>();
1194          * 
1195          * List<GroupDefinition> componentGroups = component.getGroups(); // per group, associate to it the artifacts for (GroupDefinition groupDefinition : groups) {
1196          * 
1197          * GroupDefinition componentGroup = componentGroups.stream().filter(p -> p.getUniqueId().equals(groupDefinition.getUniqueId())).findFirst().orElse(null); if (componentGroup != null) { List<String> componentArtifacts =
1198          * componentGroup.getArtifacts(); int artifactsSizeInGroup = componentArtifacts == null ? 0 : componentArtifacts.size(); List<String> artifactsToDissociate = groupDefinition.getArtifacts();
1199          * 
1200          * // if no artifcats sent if (artifactsToDissociate == null || true == artifactsToDissociate.isEmpty()) { continue; }
1201          * 
1202          * if (artifactsSizeInGroup > 0) {
1203          * 
1204          * boolean containsAll = componentArtifacts.containsAll(artifactsToDissociate); if (false == containsAll) { // At least one artifact is // not associated to the // group log.debug("Some of the artifacts already dissociated to group {}" ,
1205          * groupDefinition.getUniqueId()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ARTIFACT_ALREADY_DISSOCIATED, componentGroup.getName())); } } else { if (artifactsSizeInGroup == 0) { if (artifactsToDissociate != null &&
1206          * false == artifactsToDissociate.isEmpty()) { log.debug("No artifact is found under the group {}" , groupDefinition.getUniqueId()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ARTIFACT_ALREADY_DISSOCIATED,
1207          * componentGroup.getName())); } } } }
1208          * 
1209          * Either<GroupDefinition, StorageOperationStatus> associateArtifactsToGroup = groupOperation.dissociateArtifactsFromGroup(groupDefinition.getUniqueId(), groupDefinition.getArtifacts(), true);
1210          * 
1211          * if (associateArtifactsToGroup.isRight()) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(associateArtifactsToGroup.right().value()); result = Either.right(componentsUtils.getResponseFormat(actionStatus));
1212          * log.debug("Failed to update group {} under component {}, error: {}", groupDefinition.getName(), component.getNormalizedName(), actionStatus.name()); return result; } updatedGroups.add(associateArtifactsToGroup.left().value());
1213          * 
1214          * }
1215          * 
1216          * result = Either.left(updatedGroups); return result;
1217          * 
1218          * } finally {
1219          * 
1220          * if (false == inTransaction) {
1221          * 
1222          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
1223          * 
1224          * } // unlock resource if (shouldLockComp && component != null) { graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); }
1225          * 
1226          * }
1227          * 
1228          * }
1229          */
1230
1231         /*
1232          * public Either<List<GroupDefinition>, ResponseFormat> createGroups(String componentId, String userId, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions, boolean shouldLockComp, boolean inTransaction) {
1233          * 
1234          * Either<List<GroupDefinition>, ResponseFormat> result = null;
1235          * 
1236          * List<GroupDefinition> groups = new ArrayList<>(); org.openecomp.sdc.be.model.Component component = null; try {
1237          * 
1238          * if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1239          * 
1240          * if (shouldLockComp && inTransaction) { BeEcompErrorManager.getInstance().logInternalFlowError("createGroups", "Cannot lock component since we are inside a transaction", ErrorSeverity.ERROR); // Cannot lock component since we are in a middle of
1241          * another // transaction. ActionStatus actionStatus = ActionStatus.INVALID_CONTENT; result = Either.right(componentsUtils.getResponseFormat(actionStatus)); return result; }
1242          * 
1243          * Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, CREATE_GROUP, true); if (validateUserExists.isRight()) { result = Either.right(validateUserExists.right().value()); return result; }
1244          * 
1245          * User user = validateUserExists.left().value();
1246          * 
1247          * ComponentParametersView componentParametersView = new ComponentParametersView(); componentParametersView.disableAll(); componentParametersView.setIgnoreGroups(false); componentParametersView.setIgnoreArtifacts(false);
1248          * componentParametersView.setIgnoreUsers(false); componentParametersView.setIgnoreComponentInstances(false);
1249          * 
1250          * Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(componentId, componentType, componentParametersView);
1251          * 
1252          * if (validateComponent.isRight()) { result = Either.right(validateComponent.right().value()); return result; } component = validateComponent.left().value();
1253          * 
1254          * if (shouldLockComp) { Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, "CreateGroups"); if (lockComponent.isRight()) { return Either.right(lockComponent.right().value()); } }
1255          * 
1256          * Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, userId); if (canWork.isRight()) { result = Either.right(canWork.right().value()); return result; }
1257          * 
1258          * for (GroupDefinition groupDefinition : groupDefinitions) { Either<GroupDefinition, ResponseFormat> createGroup = this.createGroup(component, user, componentType, groupDefinition, true); if (createGroup.isRight()) {
1259          * log.debug("Failed to create group {}." , groupDefinition ); result = Either.right(createGroup.right().value()); return result; } GroupDefinition createdGroup = createGroup.left().value(); groups.add(createdGroup); } }
1260          * 
1261          * result = Either.left(groups); return result;
1262          * 
1263          * } finally {
1264          * 
1265          * if (false == inTransaction) {
1266          * 
1267          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
1268          * 
1269          * } // unlock resource if (shouldLockComp && component != null) { graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); }
1270          * 
1271          * }
1272          * 
1273          * }
1274          * 
1275          * public Either<GroupDefinition, ResponseFormat> createGroup(Component component, User user, ComponentTypeEnum componentType, GroupDefinition groupDefinition, boolean inTransaction) {
1276          * 
1277          * Either<GroupDefinition, ResponseFormat> result = null;
1278          * 
1279          * log.trace("Going to create group {}" , groupDefinition);
1280          * 
1281          * try {
1282          * 
1283          * // 3. verify group not already exist List<GroupDefinition> groups = component.getGroups(); boolean found = false; if (groups != null && false == groups.isEmpty()) {
1284          * 
1285          * GroupDefinition existGroupDef = groups.stream().filter(p -> p.getName().equalsIgnoreCase(groupDefinition.getName())).findFirst().orElse(null);
1286          * 
1287          * found = existGroupDef != null; }
1288          * 
1289          * if (true == found) { String componentTypeForResponse = getComponentTypeForResponse(component); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ALREADY_EXIST, groupDefinition.getName(), component.getNormalizedName(),
1290          * componentTypeForResponse)); return result; }
1291          * 
1292          * // 4. verify type of group exist String groupType = groupDefinition.getType(); if (groupType == null || groupType.isEmpty()) { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_MISSING_GROUP_TYPE,
1293          * groupDefinition.getName())); return result; } Either<GroupTypeDefinition, StorageOperationStatus> getGroupType = groupTypeOperation.getLatestGroupTypeByType(groupType, true); if (getGroupType.isRight()) { StorageOperationStatus status =
1294          * getGroupType.right().value(); if (status == StorageOperationStatus.NOT_FOUND) { BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "group type " + groupType + " cannot be found", ErrorSeverity.INFO); result =
1295          * Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, groupType)); return result; } else { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); return result; } }
1296          * 
1297          * // 6. verify the component instances type are allowed according to // the member types in the group type GroupTypeDefinition groupTypeDefinition = getGroupType.left().value();
1298          * 
1299          * Either<Boolean, ResponseFormat> areValidMembers = verifyComponentInstancesAreValidMembers(component, componentType, groupDefinition.getName(), groupType, groupDefinition.getMembers(), groupTypeDefinition.getMembers());
1300          * 
1301          * if (areValidMembers.isRight()) { ResponseFormat responseFormat = areValidMembers.right().value(); result = Either.right(responseFormat); return result; }
1302          * 
1303          * // 7. verify the artifacts belongs to the component Either<Boolean, ResponseFormat> areValidArtifacts = verifyArtifactsBelongsToComponent(component, groupDefinition.getArtifacts(), CREATE_GROUP); if (areValidArtifacts.isRight()) {
1304          * ResponseFormat responseFormat = areValidArtifacts.right().value(); result = Either.right(responseFormat); return result; }
1305          * 
1306          * NodeTypeEnum nodeTypeEnum = componentType.getNodeType();
1307          * 
1308          * // add invariantUUID String invariantUUID = UniqueIdBuilder.buildInvariantUUID(); groupDefinition.setInvariantUUID(invariantUUID);
1309          * 
1310          * // add groupUUID String groupUUID = UniqueIdBuilder.generateUUID(); groupDefinition.setGroupUUID(groupUUID);
1311          * 
1312          * // add version groupDefinition.setVersion(INITIAL_VERSION);
1313          * 
1314          * // set groupType uid groupDefinition.setTypeUid(groupTypeDefinition.getUniqueId());
1315          * 
1316          * Either<GroupDefinition, StorageOperationStatus> addGroupToGraph = groupOperation.addGroup(nodeTypeEnum, component.getUniqueId(), groupDefinition, true);
1317          * 
1318          * if (addGroupToGraph.isRight()) { StorageOperationStatus storageOperationStatus = addGroupToGraph.right().value(); ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageOperationStatus); result =
1319          * Either.right(componentsUtils.getResponseFormat(actionStatus)); log.debug("Failed to create group {} under component {}, error: {}", groupDefinition.getName(), component.getNormalizedName(), actionStatus.name()); } else { GroupDefinition
1320          * groupDefinitionCreated = addGroupToGraph.left().value(); result = Either.left(groupDefinitionCreated); }
1321          * 
1322          * return result;
1323          * 
1324          * } finally {
1325          * 
1326          * if (false == inTransaction) {
1327          * 
1328          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
1329          * 
1330          * }
1331          * 
1332          * }
1333          * 
1334          * }
1335          * 
1336          * public Either<List<GroupDefinition>, ResponseFormat> updateVfModuleGroupNames(String resourceSystemName, List<GroupDefinition> groups, boolean inTransaction) { List<GroupDefinition> updatedGroups = new ArrayList<>();
1337          * Either<List<GroupDefinition>, ResponseFormat> updateGroupNamesRes = Either.left(updatedGroups); Either<GroupDefinition, StorageOperationStatus> updateGroupNameRes; Either<String, ResponseFormat> validateGenerateGroupNameRes; int counter; for
1338          * (GroupDefinition group : groups) { if (!group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && !Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(group.getName()).matches()) { continue; } counter =
1339          * Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1]); validateGenerateGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, group.getDescription(), counter); if (validateGenerateGroupNameRes.isRight()) {
1340          * updateGroupNamesRes = Either.right(validateGenerateGroupNameRes.right().value()); break; } updateGroupNameRes = groupOperation.updateGroupName(group.getUniqueId(), validateGenerateGroupNameRes.left().value(), inTransaction); if
1341          * (updateGroupNameRes.isRight()) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(updateGroupNameRes.right().value()); updateGroupNamesRes = Either.right(componentsUtils.getResponseFormat(actionStatus)); break; }
1342          * updatedGroups.add(updateGroupNameRes.left().value()); } return updateGroupNamesRes; }
1343          */
1344
1345         private Either<List<GroupProperty>, ResponseFormat> updateGroupPropertiesValue(String componentId, GroupDefinition currentGroup, List<GroupProperty> groupPropertyToUpdate, boolean inTransaction) {
1346                 Either<List<GroupProperty>, ResponseFormat> result;
1347
1348                 Either<List<GroupProperty>, StorageOperationStatus> eitherUpdate = groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, groupPropertyToUpdate);
1349                 if (eitherUpdate.isRight()) {
1350                         ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(eitherUpdate.right().value());
1351                         result = Either.right(componentsUtils.getResponseFormat(actionStatus));
1352                 } else {
1353                         result = Either.left(eitherUpdate.left().value());
1354                 }
1355                 return result;
1356         }
1357
1358         public Either<Boolean, ResponseFormat> validateGenerateVfModuleGroupNames(List<ArtifactTemplateInfo> allGroups, String resourceSystemName, int startGroupCounter) {
1359                 Either<Boolean, ResponseFormat> validateGenerateGroupNamesRes = Either.left(true);
1360                 Collections.sort(allGroups, (art1, art2) -> ArtifactTemplateInfo.compareByGroupName(art1, art2));
1361                 for (ArtifactTemplateInfo group : allGroups) {
1362                         Either<String, ResponseFormat> validateGenerateGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, group.getDescription(), startGroupCounter++);
1363                         if (validateGenerateGroupNameRes.isRight()) {
1364                                 validateGenerateGroupNamesRes = Either.right(validateGenerateGroupNameRes.right().value());
1365                                 break;
1366                         }
1367                         group.setGroupName(validateGenerateGroupNameRes.left().value());
1368                 }
1369                 return validateGenerateGroupNamesRes;
1370         }
1371
1372         /**
1373          * Generate module name from resourceName, description and counter
1374          * 
1375          * @param resourceSystemName
1376          * @param description
1377          * @param groupCounter
1378          * @return
1379          */
1380         private Either<String, ResponseFormat> validateGenerateVfModuleGroupName(String resourceSystemName, String description, int groupCounter) {
1381                 Either<String, ResponseFormat> validateGenerateGroupNameRes;
1382                 if (resourceSystemName != null && description != null && Pattern.compile(Constants.MODULE_DESC_PATTERN).matcher(description).matches()) {
1383                         final String fileName = description.replaceAll("\\.\\.", "\\.");
1384                         validateGenerateGroupNameRes = Either.left(String.format(Constants.MODULE_NAME_FORMAT, resourceSystemName, FilenameUtils.removeExtension(fileName), groupCounter));
1385                 } else {
1386                         validateGenerateGroupNameRes = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME));
1387                 }
1388                 return validateGenerateGroupNameRes;
1389         }
1390
1391         public Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNames(Map<String, GroupDefinition> groups, String resourceSystemName) {
1392
1393                 Map<String, GroupDefinition> updatedNamesGroups = new HashMap<>();
1394                 Either<Map<String, GroupDefinition>, ResponseFormat> result = Either.left(updatedNamesGroups);
1395                 for (Entry<String, GroupDefinition> groupEntry : groups.entrySet()) {
1396                         GroupDefinition curGroup = groupEntry.getValue();
1397                         String groupType = curGroup.getType();
1398                         String groupName = groupEntry.getKey();
1399                         int counter;
1400                         String description;
1401                         Either<String, ResponseFormat> newGroupNameRes;
1402                         if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && !Pattern.compile(Constants.MODULE_NEW_NAME_PATTERN).matcher(groupName).matches()) {
1403
1404                                 if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupEntry.getKey()).matches()) {
1405                                         counter = Integer.parseInt(groupEntry.getKey().split(Constants.MODULE_NAME_DELIMITER)[1]);
1406                                         description = curGroup.getDescription();
1407                                 } else {
1408                                         counter = getNextVfModuleNameCounter(updatedNamesGroups);
1409                                         description = groupName;
1410                                 }
1411                                 newGroupNameRes = validateGenerateVfModuleGroupName(resourceSystemName, description, counter);
1412                                 if (newGroupNameRes.isRight()) {
1413                                         log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
1414                                         result = Either.right(newGroupNameRes.right().value());
1415                                         break;
1416                                 }
1417                                 groupName = newGroupNameRes.left().value();
1418                                 curGroup.setName(groupName);
1419                         }
1420                         updatedNamesGroups.put(groupName, curGroup);
1421                 }
1422                 return result;
1423         }
1424
1425         public int getNextVfModuleNameCounter(Map<String, GroupDefinition> groups) {
1426                 int counter = 0;
1427                 if (groups != null && !groups.isEmpty()) {
1428                         counter = getNextVfModuleNameCounter(groups.values());
1429                 }
1430                 return counter;
1431         }
1432
1433         public int getNextVfModuleNameCounter(Collection<GroupDefinition> groups) {
1434                 int counter = 0;
1435                 if (groups != null && !groups.isEmpty()) {
1436                         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())
1437                                         .map(group -> Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1])).collect(Collectors.toList());
1438                         counter = (counters == null || counters.isEmpty()) ? 0 : counters.stream().max((a, b) -> Integer.compare(a, b)).get() + 1;
1439                 }
1440                 return counter;
1441         }
1442
1443         public Either<List<GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesOnGraph(List<GroupDefinition> groups, Component component, boolean inTransaction) {
1444                 List<GroupDefinition> updatedGroups = new ArrayList<>();
1445                 Either<List<GroupDefinition>, ResponseFormat> result = Either.left(updatedGroups);
1446
1447                 for (GroupDefinition group : groups) {
1448                         String groupType = group.getType();
1449                         String oldGroupName = group.getName();
1450                         String newGroupName;
1451                         Either<String, ResponseFormat> newGroupNameRes;
1452                         Either<GroupDefinition, StorageOperationStatus> updateGroupNameRes;
1453                         int counter;
1454                         if (groupType.equals(Constants.DEFAULT_GROUP_VF_MODULE) && Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(oldGroupName).matches()) {
1455                                 counter = Integer.parseInt(group.getName().split(Constants.MODULE_NAME_DELIMITER)[1]);
1456                                 newGroupNameRes = validateGenerateVfModuleGroupName(component.getSystemName(), group.getDescription(), counter);
1457                                 if (newGroupNameRes.isRight()) {
1458                                         log.debug("Failed to generate new vf module group name. Status is {} ", newGroupNameRes.right().value());
1459                                         result = Either.right(newGroupNameRes.right().value());
1460                                         break;
1461                                 }
1462                                 newGroupName = newGroupNameRes.left().value();
1463                                 group.setName(newGroupName);
1464
1465                         }
1466                         updatedGroups.add(group);
1467
1468                 }
1469
1470                 result = Either.left(updatedGroups);
1471                 return result;
1472         }
1473
1474         /*
1475          * public Either<List<GroupDefinition>, ResponseFormat> createGroups(Component component, User user, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions, boolean inTransaction) {
1476          * 
1477          * List<GroupDefinition> generatedGroups = new ArrayList<>(); Either<List<GroupDefinition>, ResponseFormat> result = Either.left(generatedGroups);
1478          * 
1479          * try {
1480          * 
1481          * if (groupDefinitions != null && false == groupDefinitions.isEmpty()) { for (GroupDefinition groupDefinition : groupDefinitions) { Either<GroupDefinition, ResponseFormat> createGroup = this.createGroup(component, user, componentType,
1482          * groupDefinition, true); if (createGroup.isRight()) { result = Either.right(createGroup.right().value()); return result; } GroupDefinition generatedGroup = createGroup.left().value(); generatedGroups.add(generatedGroup); } }
1483          * 
1484          * return result; } finally {
1485          * 
1486          * if (false == inTransaction) {
1487          * 
1488          * if (result == null || result.isRight()) { log.debug("Going to execute rollback on create group."); titanDao.rollback(); } else { log.debug("Going to execute commit on create group."); titanDao.commit(); }
1489          * 
1490          * }
1491          * 
1492          * }
1493          * 
1494          * }
1495          */
1496
1497         public Either<GroupDefinitionInfo, ResponseFormat> getGroupInstWithArtifactsById(ComponentTypeEnum componentType, String componentId, String componentInstanceId, String groupInstId, String userId, boolean inTransaction) {
1498                 Either<GroupDefinitionInfo, ResponseFormat> result = null;
1499
1500                 // Validate user exist
1501                 Either<User, ResponseFormat> validateUserExists = validateUserExists(userId, UPDATE_GROUP, true);
1502
1503                 if (validateUserExists.isRight()) {
1504                         result = Either.right(validateUserExists.right().value());
1505                         return result;
1506                 }
1507
1508                 // Validate component exist
1509                 org.openecomp.sdc.be.model.Component component = null;
1510                 String realComponentId = componentId;
1511
1512                 try {
1513                         ComponentParametersView componentParametersView = new ComponentParametersView();
1514                         componentParametersView.disableAll();
1515                         componentParametersView.setIgnoreUsers(false);
1516                         componentParametersView.setIgnoreComponentInstances(false);
1517                         componentParametersView.setIgnoreArtifacts(false);
1518
1519                         Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(realComponentId, componentType, componentParametersView);
1520                         if (validateComponent.isRight()) {
1521                                 result = Either.right(validateComponent.right().value());
1522                                 return result;
1523                         }
1524                         component = validateComponent.left().value();
1525                         Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceRes = findComponentInstanceAndGroupInstanceOnComponent(component, componentInstanceId, groupInstId);
1526
1527                         if (findComponentInstanceAndGroupInstanceRes.isRight()) {
1528                                 log.debug("Failed to get group {} . Status is {} ", groupInstId, findComponentInstanceAndGroupInstanceRes.right().value());
1529                                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(findComponentInstanceAndGroupInstanceRes.right().value()));
1530                                 result = Either.right(responseFormat);
1531                                 return result;
1532                         }
1533
1534                         GroupInstance group = findComponentInstanceAndGroupInstanceRes.left().value().getRight();
1535                         ComponentInstance componentInstance = findComponentInstanceAndGroupInstanceRes.left().value().getLeft();
1536
1537                         Boolean isBase = null;// Constants.IS_BASE;
1538                         List<? extends GroupProperty> props = group.convertToGroupInstancesProperties();
1539                         if (props != null && !props.isEmpty()) {
1540                                 Optional<? extends GroupProperty> isBasePropOp = props.stream().filter(p -> p.getName().equals(Constants.IS_BASE)).findAny();
1541                                 if (isBasePropOp.isPresent()) {
1542                                         GroupProperty propIsBase = isBasePropOp.get();
1543                                         isBase = Boolean.parseBoolean(propIsBase.getValue());
1544
1545                                 } else {
1546                                         BeEcompErrorManager.getInstance().logInvalidInputError(GET_GROUP, "failed to find prop isBase " + component.getNormalizedName(), ErrorSeverity.INFO);
1547                                         // return
1548                                         // Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
1549
1550                                 }
1551                         }
1552
1553                         List<ArtifactDefinitionInfo> artifacts = new ArrayList<>();
1554                         List<String> artifactsIds = group.getArtifacts();
1555                         if (artifactsIds != null && !artifactsIds.isEmpty()) {
1556
1557                                 List<ComponentInstance> instances = component.getComponentInstances();
1558                                 if (instances != null) {
1559                                         Optional<ComponentInstance> findFirst = instances.stream().filter(i -> i.getUniqueId().equals(componentInstanceId)).findFirst();
1560                                         if (findFirst.isPresent()) {
1561                                                 ComponentInstance ci = findFirst.get();
1562                                                 Map<String, ArtifactDefinition> deploymentArtifacts = ci.getDeploymentArtifacts();
1563                                                 for (String id : artifactsIds) {
1564                                                         Optional<ArtifactDefinition> artOp = deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst();
1565                                                         if (artOp.isPresent()) {
1566                                                                 artifacts.add(new ArtifactDefinitionInfo(artOp.get()));
1567                                                         }
1568                                                 }
1569                                                 List<String> instArtifactsIds = group.getGroupInstanceArtifacts();
1570                                                 for (String id : instArtifactsIds) {
1571                                                         Optional<ArtifactDefinition> artOp = deploymentArtifacts.values().stream().filter(a -> a.getUniqueId().equals(id)).findFirst();
1572                                                         if (artOp.isPresent()) {
1573                                                                 artifacts.add(new ArtifactDefinitionInfo(artOp.get()));
1574                                                         }
1575                                                 }
1576                                         }
1577
1578                                 }
1579                         }
1580                         GroupDefinitionInfo resultInfo = new GroupDefinitionInfo(group);
1581                         resultInfo.setIsBase(isBase);
1582                         if (!artifacts.isEmpty())
1583                                 resultInfo.setArtifacts(artifacts);
1584
1585                         result = Either.left(resultInfo);
1586
1587                         return result;
1588
1589                 } finally {
1590
1591                         if (false == inTransaction) {
1592
1593                                 if (result == null || result.isRight()) {
1594                                         log.debug("Going to execute rollback on create group.");
1595                                         titanDao.rollback();
1596                                 } else {
1597                                         log.debug("Going to execute commit on create group.");
1598                                         titanDao.commit();
1599                                 }
1600
1601                         }
1602
1603                 }
1604         }
1605
1606         private Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> findComponentInstanceAndGroupInstanceOnComponent(Component component, String componentInstanceId, String groupInstId) {
1607
1608                 Either<ImmutablePair<ComponentInstance, GroupInstance>, StorageOperationStatus> result = null;
1609                 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
1610                         Optional<GroupInstance> foundGroup;
1611                         Optional<ComponentInstance> foundComponent = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(componentInstanceId)).findFirst();
1612                         if (foundComponent.isPresent() && CollectionUtils.isNotEmpty(foundComponent.get().getGroupInstances())) {
1613                                 foundGroup = foundComponent.get().getGroupInstances().stream().filter(gi -> gi.getUniqueId().equals(groupInstId)).findFirst();
1614                                 if (foundGroup.isPresent()) {
1615                                         result = Either.left(new ImmutablePair<>(foundComponent.get(), foundGroup.get()));
1616                                 }
1617                         }
1618                 }
1619                 if (result == null) {
1620                         result = Either.right(StorageOperationStatus.NOT_FOUND);
1621                 }
1622                 return result;
1623         }
1624
1625         private int getLatestIntProperty(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues, PropertyNames propertyKey) {
1626                 String value;
1627                 if (newValues.containsKey(propertyKey)) {
1628                         value = newValues.get(propertyKey);
1629                 } else {
1630                         value = parentValues.get(propertyKey);
1631                 }
1632                 return Integer.valueOf(value);
1633         }
1634
1635         private boolean isPropertyChanged(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues, final PropertyNames minInstances) {
1636                 return newValues.containsKey(minInstances) && newValues.containsKey(minInstances) && !newValues.get(minInstances).equals(parentValues.get(minInstances));
1637         }
1638
1639         private Either<Boolean, ResponseFormat> validateMinMaxAndInitialCountPropertyLogicVF(Map<PropertyNames, String> newValues, Map<PropertyNames, String> parentValues) {
1640
1641                 int latestMaxInstances = getLatestIntProperty(newValues, parentValues, PropertyNames.MAX_INSTANCES);
1642                 int latestInitialCount = getLatestIntProperty(newValues, parentValues, PropertyNames.INITIAL_COUNT);
1643                 int latestMinInstances = getLatestIntProperty(newValues, parentValues, PropertyNames.MIN_INSTANCES);
1644                 Either<Boolean, ResponseFormat> result = Either.left(true);
1645
1646                 if (isPropertyChanged(newValues, parentValues, PropertyNames.INITIAL_COUNT) && result.isLeft()) {
1647                         if (latestInitialCount > latestMaxInstances || latestInitialCount < latestMinInstances) {
1648                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE, PropertyNames.INITIAL_COUNT.getPropertyName(), String.valueOf(latestMinInstances), String.valueOf(latestMaxInstances)));
1649                         }
1650                 }
1651                 if (isPropertyChanged(newValues, parentValues, PropertyNames.MAX_INSTANCES) && result.isLeft()) {
1652                         if (latestMaxInstances < latestInitialCount) {
1653                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyNames.MAX_INSTANCES.getPropertyName(), "higher", String.valueOf(latestInitialCount)));
1654                         }
1655
1656                 }
1657                 if (isPropertyChanged(newValues, parentValues, PropertyNames.MIN_INSTANCES) && result.isLeft()) {
1658                         if (latestMinInstances > latestInitialCount) {
1659                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER, PropertyNames.MIN_INSTANCES.getPropertyName(), "lower", String.valueOf(latestInitialCount)));
1660                         }
1661
1662                 }
1663                 return result;
1664         }
1665
1666         private Either<Boolean, ResponseFormat> validateMinMaxAndInitialCountPropertyLogic(Map<PropertyNames, String> newValues, Map<PropertyNames, String> currValues, Map<PropertyNames, String> parentValues) {
1667
1668                 Either<Boolean, ResponseFormat> result;
1669                 for (Entry<PropertyNames, String> entry : newValues.entrySet()) {
1670                         PropertyNames currPropertyName = entry.getKey();
1671                         if (currPropertyName == PropertyNames.MIN_INSTANCES) {
1672                                 String minValue = parentValues.get(PropertyNames.MIN_INSTANCES);
1673                                 String maxValue = newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MAX_INSTANCES) : currValues.get(PropertyNames.INITIAL_COUNT);
1674                                 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1675                                                 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1676                                 if (result.isRight()) {
1677                                         return result;
1678                                 }
1679                         } else if (currPropertyName == PropertyNames.INITIAL_COUNT) {
1680                                 String minValue = newValues.containsKey(PropertyNames.MIN_INSTANCES) ? newValues.get(PropertyNames.MIN_INSTANCES) : currValues.get(PropertyNames.MIN_INSTANCES);
1681                                 String maxValue = newValues.containsKey(PropertyNames.MAX_INSTANCES) ? newValues.get(PropertyNames.MAX_INSTANCES) : currValues.get(PropertyNames.MAX_INSTANCES);
1682                                 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1683                                                 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1684                                 if (result.isRight()) {
1685                                         return result;
1686                                 }
1687                         } else if (currPropertyName == PropertyNames.MAX_INSTANCES) {
1688                                 String minValue = newValues.containsKey(PropertyNames.INITIAL_COUNT) ? newValues.get(PropertyNames.MIN_INSTANCES) : currValues.get(PropertyNames.INITIAL_COUNT);
1689                                 String maxValue = parentValues.get(PropertyNames.MAX_INSTANCES);
1690                                 result = validateValueInRange(new ImmutablePair<PropertyNames, String>(currPropertyName, entry.getValue()), new ImmutablePair<PropertyNames, String>(PropertyNames.MIN_INSTANCES, minValue),
1691                                                 new ImmutablePair<PropertyNames, String>(PropertyNames.MAX_INSTANCES, maxValue));
1692                                 if (result.isRight()) {
1693                                         return result;
1694                                 }
1695                         }
1696                 }
1697                 return Either.left(true);
1698         }
1699
1700         private Either<Boolean, ResponseFormat> validateValueInRange(ImmutablePair<PropertyNames, String> newValue, ImmutablePair<PropertyNames, String> min, ImmutablePair<PropertyNames, String> max) {
1701                 Either<Boolean, ResponseFormat> result;
1702                 final String warnMessage = "Failed to validate {} as property value of {}. It must be not higher than {}, and not lower than {}.";
1703                 int newValueInt = parseIntValue(newValue.getValue(), newValue.getKey());
1704                 int minInt = parseIntValue(min.getValue(), min.getKey());
1705                 int maxInt = parseIntValue(max.getValue(), max.getKey());
1706                 if (newValueInt < 0 || minInt < 0 || maxInt < 0) {
1707                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY));
1708                 } else if (newValueInt < minInt || newValueInt > maxInt) {
1709                         log.debug(warnMessage, newValue.getValue(), newValue.getKey().getPropertyName(), min.getValue(), max.getValue());
1710                         result = Either
1711                                         .right(componentsUtils.getResponseFormat(ActionStatus.INVALID_GROUP_MIN_MAX_INSTANCES_PROPERTY_VALUE, newValue.getKey().getPropertyName(), maxInt == Integer.MAX_VALUE ? Constants.UNBOUNDED : max.getValue(), min.getValue()));
1712                 } else {
1713                         result = Either.left(true);
1714                 }
1715                 return result;
1716         }
1717
1718         private int parseIntValue(String value, PropertyNames propertyName) {
1719                 int result;
1720                 if (propertyName == PropertyNames.MAX_INSTANCES) {
1721                         result = convertIfUnboundMax(value);
1722                 } else if (NumberUtils.isNumber(value)) {
1723                         result = Integer.parseInt(value);
1724                 } else {
1725                         result = -1;
1726                 }
1727                 return result;
1728         }
1729
1730         /**
1731          * validates received new property values and updates group instance in case of success
1732          * 
1733          * @param oldGroupInstance
1734          * @param groupInstanceId
1735          * @param newProperties
1736          * @param inTransaction
1737          * @return
1738          */
1739         public Either<GroupInstance, ResponseFormat> validateAndUpdateGroupInstancePropertyValues(String componentId, String instanceId, GroupInstance oldGroupInstance, List<GroupInstanceProperty> newProperties, boolean inTransaction) {
1740
1741                 Either<GroupInstance, ResponseFormat> actionResult = null;
1742                 Either<GroupInstance, StorageOperationStatus> updateGroupInstanceResult = null;
1743                 Either<List<GroupInstanceProperty>, ResponseFormat> validateRes = validateReduceGroupInstancePropertiesBeforeUpdate(oldGroupInstance, newProperties);
1744                 if (validateRes.isRight()) {
1745                         log.debug("Failed to validate group instance {} properties before update. ", oldGroupInstance.getName());
1746                         actionResult = Either.right(validateRes.right().value());
1747                 }
1748                 if (actionResult == null) {
1749                         List<GroupInstanceProperty> validatedReducedNewProperties = validateRes.left().value();
1750                         updateGroupInstanceResult = groupsOperation.updateGroupInstancePropertyValuesOnGraph(componentId, instanceId, oldGroupInstance, validatedReducedNewProperties);
1751                         if (updateGroupInstanceResult.isRight()) {
1752                                 log.debug("Failed to update group instance {} property values. ", oldGroupInstance.getName());
1753                                 actionResult = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateGroupInstanceResult.right().value())));
1754                         }
1755                 }
1756                 if (actionResult == null) {
1757                         actionResult = Either.left(updateGroupInstanceResult.left().value());
1758                 }
1759                 return actionResult;
1760         }
1761
1762         private Either<List<GroupInstanceProperty>, ResponseFormat> validateReduceGroupInstancePropertiesBeforeUpdate(GroupInstance oldGroupInstance, List<GroupInstanceProperty> newProperties) {
1763
1764                 Either<Boolean, ResponseFormat> validationRes = null;
1765                 Either<List<GroupInstanceProperty>, ResponseFormat> actionResult;
1766                 Map<String, GroupInstanceProperty> existingProperties = oldGroupInstance.convertToGroupInstancesProperties().stream().collect(Collectors.toMap(p -> p.getName(), p -> p));
1767                 Map<PropertyNames, String> newPropertyValues = new EnumMap<>(PropertyNames.class);
1768                 List<GroupInstanceProperty> reducedProperties = new ArrayList<>();
1769                 String currPropertyName;
1770                 try {
1771                         for (GroupInstanceProperty currNewProperty : newProperties) {
1772                                 currPropertyName = currNewProperty.getName();
1773                                 validationRes = handleAndAddProperty(reducedProperties, newPropertyValues, currNewProperty, existingProperties.get(currPropertyName));
1774                                 if (validationRes.isRight()) {
1775                                         log.debug("Failed to handle property {} of group instance {}. ", currPropertyName, oldGroupInstance.getName());
1776                                         break;
1777                                 }
1778                         }
1779                         if (validationRes == null || validationRes.isLeft()) {
1780                                 Map<PropertyNames, String> existingPropertyValues = new EnumMap<>(PropertyNames.class);
1781                                 Map<PropertyNames, String> parentPropertyValues = new EnumMap<>(PropertyNames.class);
1782                                 fillValuesAndParentValuesFromExistingProperties(existingProperties, existingPropertyValues, parentPropertyValues);
1783                                 validationRes = validateMinMaxAndInitialCountPropertyLogic(newPropertyValues, existingPropertyValues, parentPropertyValues);
1784                         }
1785                         if (validationRes.isLeft()) {
1786                                 actionResult = Either.left(reducedProperties);
1787                         } else {
1788                                 actionResult = Either.right(validationRes.right().value());
1789                         }
1790                 } catch (Exception e) {
1791                         log.error("Exception occured during validation and reducing group instance properties. The message is {}", e.getMessage(), e);
1792                         actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1793                 }
1794                 return actionResult;
1795         }
1796
1797         private void fillValuesAndParentValuesFromExistingProperties(Map<String, GroupInstanceProperty> existingProperties, Map<PropertyNames, String> propertyValues, Map<PropertyNames, String> parentPropertyValues) {
1798                 PropertyNames[] allPropertyNames = PropertyNames.values();
1799                 for (PropertyNames name : allPropertyNames) {
1800                         if (isUpdatable(name)) {
1801                                 propertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getValue()));
1802                                 parentPropertyValues.put(name, String.valueOf(existingProperties.get(name.getPropertyName()).getParentValue()));
1803                         }
1804                 }
1805         }
1806
1807         private Either<Boolean, ResponseFormat> handleAndAddProperty(List<GroupInstanceProperty> reducedProperties, Map<PropertyNames, String> newPropertyValues, GroupInstanceProperty currNewProperty, GroupInstanceProperty currExistingProperty) {
1808
1809                 Either<Boolean, ResponseFormat> validationRes = null;
1810                 String currPropertyName = currNewProperty.getName();
1811                 PropertyNames propertyName = PropertyNames.findName(currPropertyName);
1812                 try {
1813                         if (currExistingProperty == null) {
1814                                 log.warn("The value of property with the name {} cannot be updated. The property not found on group instance. ", currPropertyName);
1815                         } else if (isUpdatable(propertyName)) {
1816                                 validationRes = validateAndUpdatePropertyValue(currNewProperty, currExistingProperty);
1817                                 if (validationRes.isRight()) {
1818                                         log.debug("Failed to validate property value {} of property {}. ", currNewProperty.getValue(), currPropertyName);
1819                                 } else {
1820                                         addPropertyUpdatedValues(reducedProperties, propertyName, newPropertyValues, currNewProperty, currExistingProperty);
1821                                 }
1822                         } else {
1823                                 validateImmutableProperty(currExistingProperty, currNewProperty);
1824                         }
1825                         if (validationRes == null) {
1826                                 validationRes = Either.left(true);
1827                         }
1828                 } catch (Exception e) {
1829                         log.error("Exception occured during handle and adding property. The message is {}", e.getMessage(), e);
1830                         validationRes = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1831                 }
1832                 return validationRes;
1833         }
1834
1835         private boolean isUpdatable(PropertyNames updatablePropertyName) {
1836                 return updatablePropertyName != null && updatablePropertyName.getUpdateBehavior().getLevelNumber() >= GroupInstancePropertyValueUpdateBehavior.UPDATABLE_ON_SERVICE_LEVEL.getLevelNumber();
1837         }
1838
1839         private void addPropertyUpdatedValues(List<GroupInstanceProperty> reducedProperties, PropertyNames propertyName, Map<PropertyNames, String> newPropertyValues, GroupInstanceProperty newProperty, GroupInstanceProperty existingProperty) {
1840
1841                 String newValue = newProperty.getValue();
1842                 if (!newValue.equals(String.valueOf(existingProperty.getValue()))) {
1843                         newProperty.setValueUniqueUid(existingProperty.getValueUniqueUid());
1844                         reducedProperties.add(newProperty);
1845                 }
1846                 if (!isEmptyMinInitialCountValue(propertyName, newValue)) {
1847                         newPropertyValues.put(propertyName, newValue);
1848                 }
1849         }
1850
1851         private boolean isEmptyMinInitialCountValue(PropertyNames propertyName, String newValue) {
1852                 boolean result = false;
1853                 if ((propertyName == PropertyNames.MIN_INSTANCES || propertyName == PropertyNames.INITIAL_COUNT) && !NumberUtils.isNumber(newValue)) {
1854                         result = true;
1855                 }
1856                 return result;
1857         }
1858
1859         private int convertIfUnboundMax(String value) {
1860
1861                 int result;
1862                 if (!NumberUtils.isNumber(value)) {
1863                         result = Integer.MAX_VALUE;
1864                 } else {
1865                         result = Integer.parseInt(value);
1866                 }
1867                 return result;
1868         }
1869
1870         private Either<Boolean, ResponseFormat> validateAndUpdatePropertyValue(GroupInstanceProperty newProperty, GroupInstanceProperty existingProperty) {
1871
1872                 Either<Boolean, ResponseFormat> validationRes = null;
1873                 String parentValue = existingProperty.getParentValue();
1874
1875                 newProperty.setParentValue(parentValue);
1876                 if (StringUtils.isEmpty(newProperty.getValue())) {
1877                         newProperty.setValue(parentValue);
1878                 }
1879                 if (StringUtils.isEmpty(existingProperty.getValue())) {
1880                         existingProperty.setValue(parentValue);
1881                 }
1882                 StorageOperationStatus status = groupOperation.validateAndUpdatePropertyValue(newProperty);
1883                 if (status != StorageOperationStatus.OK) {
1884                         log.debug("Failed to validate property value {} of property with name {}. Status is {}. ", newProperty.getValue(), newProperty.getName(), status);
1885                         validationRes = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status)));
1886                 }
1887                 if (validationRes == null) {
1888                         validationRes = Either.left(true);
1889                 }
1890                 return validationRes;
1891         }
1892
1893         private void validateImmutableProperty(GroupProperty oldProperty, GroupProperty newProperty) {
1894                 if (oldProperty.getValue() == null && newProperty.getValue() != null || oldProperty.getValue() != null && !oldProperty.getValue().equals(newProperty.getValue())) {
1895                         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());
1896                 }
1897         }
1898
1899         public Either<List<GroupDefinition>, ResponseFormat> createGroups(Component component, User user, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions) {
1900
1901                 Map<String, GroupDataDefinition> groups = new HashMap<>();
1902                 // Map<String, MapPropertiesDataDefinition> groupsPropertiesMap = new HashMap<>();
1903                 Either<List<GroupDefinition>, ResponseFormat> result = null;
1904                 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1905                 Either<Map<String, DataTypeDefinition>, TitanOperationStatus> allDataTypes = dataTypeCache.getAll();
1906                 if (allDataTypes.isRight()) {
1907                         TitanOperationStatus status = allDataTypes.right().value();
1908                         BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToGroup", "Failed to add property to group. Status is " + status, ErrorSeverity.ERROR);
1909                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status))));
1910
1911                 }
1912
1913                 // handle groups and convert to tosca data
1914                 if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1915                         for (GroupDefinition groupDefinition : groupDefinitions) {
1916                                 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, user, componentType, groupDefinition, allDataTypes.left().value());
1917                                 if (handleGroupRes.isRight()) {
1918                                         result = Either.right(handleGroupRes.right().value());
1919                                         break;
1920                                 }
1921                                 GroupDefinition handledGroup = handleGroupRes.left().value();
1922                                 groups.put(handledGroup.getName(), new GroupDataDefinition(handledGroup));
1923
1924                         }
1925                 }
1926                 if (result == null) {
1927                         createGroupsResult = groupsOperation.createGroups(component, user, componentType, groups);
1928                         if (createGroupsResult.isRight()) {
1929                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1930                         }
1931                 }
1932                 if (result == null) {
1933                         result = Either.left(createGroupsResult.left().value());
1934                 }
1935                 return result;
1936         }
1937
1938         public Either<List<GroupDefinition>, ResponseFormat> addGroups(Component component, User user, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions) {
1939
1940                 Either<List<GroupDefinition>, ResponseFormat> result = null;
1941                 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1942                 List<GroupDataDefinition> groups = new ArrayList<>();
1943
1944                 Either<Map<String, DataTypeDefinition>, TitanOperationStatus> allDataTypes = dataTypeCache.getAll();
1945                 if (allDataTypes.isRight()) {
1946                         TitanOperationStatus status = allDataTypes.right().value();
1947                         BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToGroup", "Failed to add property to group. Status is " + status, ErrorSeverity.ERROR);
1948                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status))));
1949
1950                 }
1951
1952                 // handle groups and convert to tosca data
1953                 if (groupDefinitions != null && !groupDefinitions.isEmpty()) {
1954                         for (GroupDefinition groupDefinition : groupDefinitions) {
1955                                 Either<GroupDefinition, ResponseFormat> handleGroupRes = handleGroup(component, user, componentType, groupDefinition, allDataTypes.left().value());
1956                                 if (handleGroupRes.isRight()) {
1957                                         result = Either.right(handleGroupRes.right().value());
1958                                         break;
1959                                 }
1960                                 GroupDefinition handledGroup = handleGroupRes.left().value();
1961                                 groups.add(new GroupDataDefinition(handledGroup));
1962                         }
1963                 }
1964                 if (result == null) {
1965                         createGroupsResult = groupsOperation.addGroups(component, user, componentType, groups);
1966                         if (createGroupsResult.isRight()) {
1967                                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1968                         }
1969                 }
1970                 if (result == null) {
1971                         result = Either.left(createGroupsResult.left().value());
1972                 }
1973                 return result;
1974         }
1975
1976         public Either<List<GroupDefinition>, ResponseFormat> deleteGroups(Component component, User user, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions) {
1977
1978                 Either<List<GroupDefinition>, ResponseFormat> result = null;
1979                 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
1980
1981                 createGroupsResult = groupsOperation.deleteGroups(component, user, componentType, groupDefinitions.stream().map(x -> new GroupDataDefinition(x)).collect(Collectors.toList()));
1982                 if (createGroupsResult.isRight()) {
1983                         result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
1984                 }
1985
1986                 if (result == null) {
1987                         result = Either.left(createGroupsResult.left().value());
1988                 }
1989                 return result;
1990         }
1991
1992         /**
1993          * Update specific group version
1994          * 
1995          * @param groupDefinition
1996          * @param inTransaction
1997          * @return
1998          */
1999         public Either<List<GroupDefinition>, ResponseFormat> updateGroups(Component component, ComponentTypeEnum componentType, List<GroupDefinition> groupDefinitions) {
2000
2001                 Either<List<GroupDefinition>, ResponseFormat> result = null;
2002                 Either<List<GroupDefinition>, StorageOperationStatus> createGroupsResult = null;
2003
2004                 createGroupsResult = groupsOperation.updateGroups(component, componentType, groupDefinitions.stream().map(x -> new GroupDataDefinition(x)).collect(Collectors.toList()));
2005                 if (createGroupsResult.isRight()) {
2006                         result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(createGroupsResult.right().value())));
2007                 }
2008
2009                 if (result == null) {
2010                         result = Either.left(createGroupsResult.left().value());
2011                 }
2012                 return result;
2013         }
2014
2015         public Either<GroupDefinition, ResponseFormat> handleGroup(Component component, User user, ComponentTypeEnum componentType, GroupDefinition groupDefinition, Map<String, DataTypeDefinition> allDAtaTypes) {
2016
2017                 Either<GroupDefinition, ResponseFormat> result = null;
2018
2019                 log.trace("Going to create group {}", groupDefinition);
2020                 // 3. verify group not already exist
2021                 List<GroupDefinition> groups = component.getGroups();
2022                 boolean found = false;
2023                 if (groups != null && false == groups.isEmpty()) {
2024
2025                         GroupDefinition existGroupDef = groups.stream().filter(p -> p.getName().equalsIgnoreCase(groupDefinition.getName())).findFirst().orElse(null);
2026
2027                         found = existGroupDef != null;
2028                 }
2029                 if (true == found) {
2030                         String componentTypeForResponse = getComponentTypeForResponse(component);
2031                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_ALREADY_EXIST, groupDefinition.getName(), component.getNormalizedName(), componentTypeForResponse));
2032                         return result;
2033                 }
2034                 // 4. verify type of group exist
2035                 String groupType = groupDefinition.getType();
2036                 if (groupType == null || groupType.isEmpty()) {
2037                         result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupDefinition.getName()));
2038                         return result;
2039                 }
2040                 Either<GroupTypeDefinition, StorageOperationStatus> getGroupType = groupTypeOperation.getLatestGroupTypeByType(groupType, true);
2041                 if (getGroupType.isRight()) {
2042                         StorageOperationStatus status = getGroupType.right().value();
2043                         if (status == StorageOperationStatus.NOT_FOUND) {
2044                                 BeEcompErrorManager.getInstance().logInvalidInputError(CREATE_GROUP, "group type " + groupType + " cannot be found", ErrorSeverity.INFO);
2045                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GROUP_TYPE_IS_INVALID, groupType));
2046                                 return result;
2047                         } else {
2048                                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
2049                                 return result;
2050                         }
2051                 }
2052                 // 6. verify the component instances type are allowed according to
2053                 // the member types in the group type
2054                 GroupTypeDefinition groupTypeDefinition = getGroupType.left().value();
2055
2056                 Either<Boolean, ResponseFormat> areValidMembers = verifyComponentInstancesAreValidMembers(component, componentType, groupDefinition.getName(), groupType, groupDefinition.getMembers(), groupTypeDefinition.getMembers());
2057
2058                 if (areValidMembers.isRight()) {
2059                         ResponseFormat responseFormat = areValidMembers.right().value();
2060                         result = Either.right(responseFormat);
2061                         return result;
2062                 }
2063                 // 7. verify the artifacts belongs to the component
2064                 Either<Boolean, ResponseFormat> areValidArtifacts = verifyArtifactsBelongsToComponent(component, groupDefinition.getArtifacts(), CREATE_GROUP);
2065                 if (areValidArtifacts.isRight()) {
2066                         ResponseFormat responseFormat = areValidArtifacts.right().value();
2067                         result = Either.right(responseFormat);
2068                         return result;
2069                 }
2070                 List<PropertyDefinition> groupTypeProperties = groupTypeDefinition.getProperties();
2071
2072                 List<GroupProperty> properties = groupDefinition.convertToGroupProperties();
2073                 List<GroupProperty> updatedGroupTypeProperties = new ArrayList<>();
2074                 if (properties != null && false == properties.isEmpty()) {
2075
2076                         if (groupTypeProperties == null || true == groupTypeProperties.isEmpty()) {
2077                                 BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "group type does not have properties", ErrorSeverity.INFO);
2078                                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.MATCH_NOT_FOUND))));
2079                         }
2080
2081                         Map<String, PropertyDefinition> groupTypePropertiesMap = groupTypeProperties.stream().collect(Collectors.toMap(p -> p.getName(), p -> p));
2082
2083                         Either<GroupProperty, TitanOperationStatus> addPropertyResult = null;
2084                         int i = 1;
2085                         for (GroupProperty prop : properties) {
2086                                 addPropertyResult = handleProperty(prop, groupTypePropertiesMap.get(prop.getName()), i, allDAtaTypes);
2087                                 if (addPropertyResult.isRight()) {
2088                                         BeEcompErrorManager.getInstance().logInvalidInputError(ADDING_GROUP, "failed to validate property", ErrorSeverity.INFO);
2089                                         return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(addPropertyResult.right().value()))));
2090                                 }
2091                                 updatedGroupTypeProperties.add(addPropertyResult.left().value());
2092
2093                                 i++;
2094                         }
2095                 }
2096                 if (groupDefinition.getUniqueId() == null) {
2097                         String uid = UniqueIdBuilder.buildGroupingUid(component.getUniqueId(), groupDefinition.getName());
2098                         groupDefinition.setUniqueId(uid);
2099                 }
2100                 groupDefinition.convertFromGroupProperties(updatedGroupTypeProperties);
2101                 groupDefinition.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID());
2102                 groupDefinition.setGroupUUID(UniqueIdBuilder.generateUUID());
2103                 groupDefinition.setVersion(INITIAL_VERSION);
2104                 groupDefinition.setTypeUid(groupTypeDefinition.getUniqueId());
2105
2106                 return Either.left(groupDefinition);
2107         }
2108
2109         public Either<GroupProperty, TitanOperationStatus> handleProperty(GroupProperty groupProperty, PropertyDefinition prop, Integer index, Map<String, DataTypeDefinition> allDataTypes) {
2110
2111                 if (prop == null) {
2112                         return Either.right(TitanOperationStatus.ILLEGAL_ARGUMENT);
2113                 }
2114
2115                 PropertyDataDefinition propDataDef = prop;
2116                 String propertyType = propDataDef.getType();
2117                 String value = groupProperty.getValue();
2118
2119                 Either<String, TitanOperationStatus> checkInnerType = propertyOperation.checkInnerType(propDataDef);
2120                 if (checkInnerType.isRight()) {
2121                         TitanOperationStatus status = checkInnerType.right().value();
2122                         return Either.right(status);
2123                 }
2124
2125                 String innerType = checkInnerType.left().value();
2126
2127                 log.debug("Before validateAndUpdatePropertyValue");
2128                 Either<Object, Boolean> isValid = propertyOperation.validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes);
2129                 log.debug("After validateAndUpdatePropertyValue. isValid = {}", isValid);
2130
2131                 String newValue = value;
2132                 if (isValid.isRight()) {
2133                         Boolean res = isValid.right().value();
2134                         if (res == false) {
2135                                 return Either.right(TitanOperationStatus.ILLEGAL_ARGUMENT);
2136                         }
2137                 } else {
2138                         Object object = isValid.left().value();
2139                         if (object != null) {
2140                                 newValue = object.toString();
2141                         }
2142                 }
2143
2144                 String uniqueId = UniqueIdBuilder.buildGroupPropertyValueUid((String) prop.getUniqueId(), index);
2145
2146                 groupProperty.setUniqueId(uniqueId);
2147                 groupProperty.setValue(newValue);
2148                 groupProperty.setType(prop.getType());
2149                 groupProperty.setDefaultValue(prop.getDefaultValue());
2150                 groupProperty.setDescription(prop.getDescription());
2151                 groupProperty.setSchema(prop.getSchema());
2152                 groupProperty.setPassword(prop.isPassword());
2153                 groupProperty.setParentUniqueId(prop.getUniqueId());
2154
2155                 log.debug("Before adding property value to graph {}", groupProperty);
2156
2157                 return Either.left(groupProperty);
2158         }
2159
2160 }