Fix set property policy tosca function issue
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / PolicyBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2021 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.openecomp.sdc.be.components.impl;
22
23 import static java.util.stream.Collectors.toMap;
24 import static org.openecomp.sdc.be.components.validation.PolicyUtils.getExcludedPolicyTypesByComponent;
25 import static org.openecomp.sdc.be.components.validation.PolicyUtils.getNextPolicyCounter;
26 import static org.openecomp.sdc.be.components.validation.PolicyUtils.validatePolicyFields;
27
28 import fj.data.Either;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.EnumMap;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Optional;
37 import java.util.Set;
38 import java.util.function.Function;
39 import java.util.stream.Collectors;
40 import org.apache.commons.collections.CollectionUtils;
41 import org.apache.commons.collections.MapUtils;
42 import org.apache.commons.lang3.StringUtils;
43 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
44 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
45 import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
46 import org.openecomp.sdc.be.components.validation.PolicyUtils;
47 import org.openecomp.sdc.be.dao.api.ActionStatus;
48 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
49 import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition;
50 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
52 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
53 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
54 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
55 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
56 import org.openecomp.sdc.be.model.Component;
57 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
58 import org.openecomp.sdc.be.model.ComponentInstance;
59 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
60 import org.openecomp.sdc.be.model.ComponentParametersView;
61 import org.openecomp.sdc.be.model.PolicyDefinition;
62 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
63 import org.openecomp.sdc.be.model.Resource;
64 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
65 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
66 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
67 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
68 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
69 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
70 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
71 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
72 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
73 import org.openecomp.sdc.common.datastructure.Wrapper;
74 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
75 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
76 import org.openecomp.sdc.common.log.enums.StatusCode;
77 import org.openecomp.sdc.common.log.wrappers.Logger;
78 import org.openecomp.sdc.exception.ResponseFormat;
79 import org.springframework.beans.factory.annotation.Autowired;
80
81 /**
82  * Provides specified business logic to create, retrieve, update, delete a policy
83  */
84 @org.springframework.stereotype.Component("policyBusinessLogic")
85 public class PolicyBusinessLogic extends BaseBusinessLogic {
86
87     private static final String DECLARE_PROPERTIES_TO_POLICIES = "declare properties to policies";
88     private static final Logger log = Logger.getLogger(PolicyBusinessLogic.class);
89     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(PolicyBusinessLogic.class.getName());
90     private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator;
91
92     @Autowired
93     public PolicyBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
94                                IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
95                                InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsOperations artifactToscaOperation) {
96         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
97             artifactToscaOperation);
98     }
99
100     @Autowired
101     public void setPropertyDeclarationOrchestrator(PropertyDeclarationOrchestrator propertyDeclarationOrchestrator) {
102         this.propertyDeclarationOrchestrator = propertyDeclarationOrchestrator;
103     }
104
105     /**
106      * Adds the newly created policy of the specified type to the component
107      *
108      * @param componentType  the type of the component
109      * @param componentId    the id of the component which the policy resides under
110      * @param policyTypeName the name of the policy type
111      * @param userId         the user creator id
112      * @param shouldLock     the flag defining if the component should be locked
113      * @return a policy or an error in a response format
114      */
115     public PolicyDefinition createPolicy(ComponentTypeEnum componentType, String componentId, String policyTypeName, String userId,
116                                          boolean shouldLock) {
117         log.trace("#createPolicy - starting to create policy of the type {} on the component {}. ", policyTypeName, componentId);
118         Component component = null;
119         boolean failed = false;
120         try {
121             component = validateAndLockComponentAndUserBeforeWriteOperation(componentType, componentId, userId, shouldLock);
122             return createPolicy(policyTypeName, component);
123         } catch (ComponentException e) {
124             failed = true;
125             throw e;
126         } finally {
127             unlockComponent(shouldLock, failed, component);
128         }
129     }
130
131     public Map<String, PolicyDefinition> createPolicies(final Component component,
132                                                         final Map<String, PolicyDefinition> incomingPolicyDefinitions) {
133         if (MapUtils.isEmpty(incomingPolicyDefinitions)) {
134             return Collections.emptyMap();
135         }
136         final Map<String, PolicyDefinition> createdPolicies = new HashMap<>();
137         for (final PolicyDefinition incomingPolicyDefinition : incomingPolicyDefinitions.values()) {
138             final String policyName = incomingPolicyDefinition.getName();
139             log.trace("Going to create policy {}", incomingPolicyDefinition);
140             loggerSupportability
141                 .log(LoggerSupportabilityActions.CREATE_GROUP_POLICY, component.getComponentMetadataForSupportLog(), StatusCode.STARTED,
142                     "Start to create policy: {} for component {}", policyName, component.getName());
143             final String policyType = incomingPolicyDefinition.getType();
144             if (StringUtils.isEmpty(policyType)) {
145                 log.debug("Policy type '{}' for policy '{}' not found.", policyType, policyName);
146                 throw new ByActionStatusComponentException(ActionStatus.POLICY_MISSING_POLICY_TYPE, policyName);
147             }
148             // create policyDefinition
149             final String policyTypeName = incomingPolicyDefinition.getPolicyTypeName();
150             PolicyDefinition createdPolicyDefinition = createPolicy(policyTypeName, component);
151             // set isFromCsar
152             createdPolicyDefinition.setToscaPresentationValue(JsonPresentationFields.IS_FROM_CSAR, true);
153             // link policy to component
154             component.addPolicy(createdPolicyDefinition);
155             // process targets
156             final Map<PolicyTargetType, List<String>> policyTargets = incomingPolicyDefinition.getTargets();
157             createdPolicyDefinition = setUpdatePolicyTargets(component, createdPolicyDefinition, policyTargets);
158             // process policy properties
159             List<PropertyDataDefinition> properties = incomingPolicyDefinition.getProperties();
160             createdPolicyDefinition = setUpdatePolicyProperties(component, createdPolicyDefinition, properties);
161             createdPolicies.put(policyName, createdPolicyDefinition);
162             loggerSupportability.log(LoggerSupportabilityActions.CREATE_POLICIES, component.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
163                 "policy {} has been created ", policyName);
164         }
165         return createdPolicies;
166     }
167
168     private PolicyDefinition setUpdatePolicyProperties(Component component, PolicyDefinition policyDefinition,
169                                                        List<PropertyDataDefinition> properties) {
170         if (CollectionUtils.isNotEmpty(properties)) {
171             PropertyDataDefinition[] propertiesArray = properties.toArray(new PropertyDataDefinition[properties.size()]);
172             List<PropertyDataDefinition> updatedPropertiesList = setComponentValidateUpdatePolicyProperties(policyDefinition.getUniqueId(),
173                 propertiesArray, component);
174             policyDefinition.setProperties(updatedPropertiesList);
175         }
176         return policyDefinition;
177     }
178
179     private PolicyDefinition setUpdatePolicyTargets(Component component, PolicyDefinition policyDefinition,
180                                                     Map<PolicyTargetType, List<String>> targets) {
181         if (MapUtils.isEmpty(targets)) {
182             return policyDefinition;
183         }
184         final List<String> componentInstancesTargetsToUpdate = targets.get(PolicyTargetType.COMPONENT_INSTANCES);
185         final List<String> groupsTargetsToUpdate = targets.get(PolicyTargetType.GROUPS);
186         if (CollectionUtils.isEmpty(componentInstancesTargetsToUpdate) && CollectionUtils.isEmpty(groupsTargetsToUpdate)) {
187             return policyDefinition;
188         }
189
190         final List<String> allTargets = joinLists(componentInstancesTargetsToUpdate, groupsTargetsToUpdate);
191
192         // update targets to uniqueIds of respective component instance
193         final List<String> targetsGroupsUniqueIds = new ArrayList<>();
194         final List<String> targetsInstanceUniqueIds = new ArrayList<>();
195         for (final String targetName : allTargets) {
196             final String groupsTargetUniqueIdForTargetName = getTargetGroupUniqueIdByTargetName(component, targetName);
197             if (groupsTargetUniqueIdForTargetName != null) {
198                 targetsGroupsUniqueIds.add(groupsTargetUniqueIdForTargetName);
199             }
200             final String instanceTargetUniqueIdForTargetName = getTargetInstanceUniqueIdByTargetName(component, targetName);
201             if (instanceTargetUniqueIdForTargetName != null) {
202                 targetsInstanceUniqueIds.add(instanceTargetUniqueIdForTargetName);
203             }
204         }
205         if (targetsGroupsUniqueIds.isEmpty() && targetsInstanceUniqueIds.isEmpty()) {
206             throw new ByActionStatusComponentException(ActionStatus.POLICY_TARGET_DOES_NOT_EXIST);
207         }
208         final EnumMap<PolicyTargetType, List<String>> updatedTargets = new EnumMap<>(PolicyTargetType.class);
209         if (!targetsGroupsUniqueIds.isEmpty()) {
210             updatedTargets.put(PolicyTargetType.GROUPS, targetsGroupsUniqueIds);
211         }
212         if (!targetsInstanceUniqueIds.isEmpty()) {
213             updatedTargets.put(PolicyTargetType.COMPONENT_INSTANCES, targetsInstanceUniqueIds);
214         }
215         policyDefinition.setTargets(updatedTargets);
216         return validateAndUpdatePolicyTargets(component, policyDefinition.getUniqueId(), policyDefinition.getTargets());
217     }
218
219     private List<String> joinLists(final List<String> a, final List<String> b) {
220         final List<String> result = new ArrayList<>();
221         if (CollectionUtils.isNotEmpty(a)) {
222             result.addAll(a);
223         }
224         if (CollectionUtils.isNotEmpty(b)) {
225             result.addAll(b);
226         }
227         return result;
228     }
229
230     private String getTargetGroupUniqueIdByTargetName(final Component component, final String targetName) {
231         return component.getGroupByInvariantName(targetName).map(GroupDataDefinition::getUniqueId).orElse(null);
232     }
233
234     private String getTargetInstanceUniqueIdByTargetName(final Component component, final String targetName) {
235         return component.getComponentInstanceByName(targetName).map(ComponentInstance::getUniqueId).orElse(null);
236     }
237
238     /**
239      * Retrieves the policy of the component by UniqueId
240      *
241      * @param componentType the type of the component
242      * @param componentId   the ID of the component
243      * @param policyId      the ID of the policy
244      * @param userId        the ID of the user
245      * @return either policy or error response
246      */
247     public PolicyDefinition getPolicy(ComponentTypeEnum componentType, String componentId, String policyId, String userId) {
248         log.trace("#getPolicy - starting to retrieve the policy {} of the component {}. ", policyId, componentId);
249         Component component = validateContainerComponentAndUserBeforeReadOperation(componentType, componentId, userId);
250         return getPolicyById(component, policyId);
251     }
252
253     /**
254      * Updates the policy of the component
255      *
256      * @param componentType the type of the component
257      * @param componentId   the id of the component which the policy resides under
258      * @param policy        the policy to update
259      * @param userId        the user modifier id
260      * @param shouldLock    the flag defining if the component should be locked
261      * @return a policy or an error in a response format
262      */
263     public PolicyDefinition updatePolicy(ComponentTypeEnum componentType, String componentId, PolicyDefinition policy, String userId,
264                                          boolean shouldLock) {
265         Component component = null;
266         boolean failed = false;
267         log.trace("#updatePolicy - starting to update the policy {} on the component {}. ", policy.getUniqueId(), componentId);
268         try {
269             component = validateAndLockComponentAndUserBeforeWriteOperation(componentType, componentId, userId, shouldLock);
270             return validateAndUpdatePolicy(component, policy);
271         } catch (ComponentException e) {
272             failed = true;
273             log.error("#updatePolicy - the exception occurred upon update of a policy of the type {} for the component {}: ", policy.getUniqueId(),
274                 componentId, e);
275             throw e;
276         } finally {
277             //TODO Andrey result = boolean
278             unlockComponent(shouldLock, failed, component);
279         }
280     }
281
282     /**
283      * Deletes the policy from the component
284      *
285      * @param componentType the type of the component
286      * @param componentId   the id of the component which the policy resides under
287      * @param policyId      the id of the policy which its properties to return
288      * @param userId        the user modifier id
289      * @param shouldLock    the flag defining if the component should be locked
290      * @return a policy or an error in a response format
291      */
292     public PolicyDefinition deletePolicy(ComponentTypeEnum componentType, String componentId, String policyId, String userId, boolean shouldLock) {
293         log.trace("#deletePolicy - starting to update the policy {} on the component {}. ", policyId, componentId);
294         Component component = null;
295         boolean failed = false;
296         try {
297             component = validateAndLockComponentAndUserBeforeWriteOperation(componentType, componentId, userId, shouldLock);
298             return deletePolicy(component, policyId);
299         } catch (ComponentException e) {
300             failed = true;
301             log.error("#deletePolicy - the exception occurred upon update of a policy of the type {} for the component {}: ", policyId, componentId,
302                 e);
303             throw e;
304         } finally {
305             unlockComponent(shouldLock, failed, component);
306         }
307     }
308
309     public Either<PolicyDefinition, ResponseFormat> undeclarePolicy(ComponentTypeEnum componentType, String componentId, String policyId,
310                                                                     String userId, boolean shouldLock) {
311         Either<PolicyDefinition, ResponseFormat> result = null;
312         log.trace("#undeclarePolicy - starting to undeclare policy {} on component {}. ", policyId, componentId);
313         Wrapper<Component> component = new Wrapper<>();
314         try {
315             validateAndLockComponentAndUserBeforeWriteOperation(componentType, componentId, userId, shouldLock);
316             ComponentParametersView componentParametersView = new ComponentParametersView();
317             componentParametersView.disableAll();
318             componentParametersView.setIgnoreComponentInstances(false);
319             componentParametersView.setIgnoreComponentInstancesProperties(false);
320             componentParametersView.setIgnorePolicies(false);
321             Either<Component, StorageOperationStatus> componentWithFilters = toscaOperationFacade
322                 .getToscaElement(componentId, componentParametersView);
323             if (componentWithFilters.isRight()) {
324                 return Either
325                     .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentWithFilters.right().value())));
326             }
327             Component containerComponent = componentWithFilters.left().value();
328             Optional<PolicyDefinition> policyCandidate = getPolicyForUndeclaration(policyId, containerComponent);
329             if (policyCandidate.isPresent()) {
330                 result = undeclarePolicy(policyCandidate.get(), containerComponent);
331             }
332             return result;
333         } catch (Exception e) {
334             log.error("#undeclarePolicy - the exception occurred upon update of a policy of type {} for component {}: ", policyId, componentId, e);
335             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, e.getMessage()));
336         } finally {
337             if (result == null || result.isRight()) {
338                 unlockComponent(shouldLock, true, component);
339             } else {
340                 unlockComponent(shouldLock, false, component);
341             }
342         }
343     }
344
345     private Either<PolicyDefinition, ResponseFormat> undeclarePolicy(PolicyDefinition policyDefinition, Component containerComponent) {
346         StorageOperationStatus undeclareStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsPolicies(containerComponent, policyDefinition);
347         if (undeclareStatus != StorageOperationStatus.OK) {
348             return Either.right(componentsUtils.getResponseFormat(undeclareStatus));
349         } else {
350             return Either.left(policyDefinition);
351         }
352     }
353
354     private Optional<PolicyDefinition> getPolicyForUndeclaration(String policyId, Component component) {
355         Map<String, PolicyDefinition> policies = component.getPolicies();
356         if (MapUtils.isNotEmpty(policies) && policies.containsKey(policyId)) {
357             return Optional.of(policies.get(policyId));
358         }
359         Map<String, List<ComponentInstanceProperty>> componentInstancesProperties =
360             MapUtils.isEmpty(component.getComponentInstancesProperties()) ? new HashMap<>() : component.getComponentInstancesProperties();
361         for (Map.Entry<String, List<ComponentInstanceProperty>> instancePropertyEntry : componentInstancesProperties.entrySet()) {
362             Optional<ComponentInstanceProperty> propertyCandidate = getPropertyForDeclaredPolicy(policyId, instancePropertyEntry.getValue());
363             if (propertyCandidate.isPresent()) {
364                 return Optional.of(PolicyUtils.getDeclaredPolicyDefinition(instancePropertyEntry.getKey(), propertyCandidate.get()));
365             }
366         }
367         return Optional.empty();
368     }
369
370     private Optional<ComponentInstanceProperty> getPropertyForDeclaredPolicy(String policyId,
371                                                                              List<ComponentInstanceProperty> componentInstanceProperties) {
372         for (ComponentInstanceProperty property : componentInstanceProperties) {
373             Optional<GetPolicyValueDataDefinition> getPolicyCandidate = property.safeGetGetPolicyValues().stream()
374                 .filter(getPolicyValue -> getPolicyValue.getPolicyId().equals(policyId)).findAny();
375             if (getPolicyCandidate.isPresent()) {
376                 return Optional.of(property);
377             }
378         }
379         return Optional.empty();
380     }
381
382     public PolicyDefinition updatePolicyTargets(ComponentTypeEnum componentTypeEnum, String componentId, String policyId,
383                                                 Map<PolicyTargetType, List<String>> targets, String userId) {
384         log.debug("updating the policy id {} targets with the components {}. ", policyId, componentId);
385         boolean failed = false;
386         try {
387             //not right error response
388             Component component = validateAndLockComponentAndUserBeforeWriteOperation(componentTypeEnum, componentId, userId, true);
389             return validateAndUpdatePolicyTargets(component, policyId, targets);
390         } catch (ComponentException e) {
391             failed = true;
392             throw e;
393         } finally {
394             unlockComponentById(failed, componentId);
395         }
396     }
397
398     private PolicyDefinition validateAndUpdatePolicyTargets(Component component, String policyId, Map<PolicyTargetType, List<String>> targets) {
399         validateTargetsExistAndTypesCorrect(component.getUniqueId(), targets);
400         return updateTargets(component.getUniqueId(), component.getPolicyById(policyId), targets, policyId);
401     }
402
403     private Component validateTargetsExistAndTypesCorrect(String componentId, Map<PolicyTargetType, List<String>> targets) {
404         Either<Component, StorageOperationStatus> componentEither = toscaOperationFacade.getToscaFullElement(componentId);
405         if (componentEither.isRight()) {
406             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
407         }
408         Component parentComponent = componentEither.left().value();
409         return validateTargetExists(parentComponent, targets.entrySet());
410     }
411
412     private Component validateTargetExists(Component parentComponent, Set<Map.Entry<PolicyTargetType, List<String>>> entries) {
413         for (Map.Entry<PolicyTargetType, List<String>> entry : entries) {
414             checkTargetNotExistOnComponentByType(parentComponent, entry);
415         }
416         return parentComponent;
417     }
418
419     private Component checkTargetNotExistOnComponentByType(Component parentComponent, Map.Entry<PolicyTargetType, List<String>> targetEntry) {
420         for (String id : targetEntry.getValue()) {
421             if (checkNotPresenceInComponentByType(parentComponent, id, targetEntry.getKey().getName())) {
422                 throw new ByActionStatusComponentException(ActionStatus.POLICY_TARGET_DOES_NOT_EXIST, id);
423             }
424         }
425         return parentComponent;
426     }
427
428     private boolean checkNotPresenceInComponentByType(Component parentComponent, String uniqueId, String type) {
429         if (type.equalsIgnoreCase(PolicyTargetType.GROUPS.getName()) && parentComponent.getGroups() != null) {
430             return !parentComponent.getGroupById(uniqueId).isPresent();
431         } else if (type.equalsIgnoreCase(PolicyTargetType.COMPONENT_INSTANCES.getName()) && parentComponent.getComponentInstances() != null) {
432             return !parentComponent.getComponentInstanceById(uniqueId).isPresent();
433         }
434         return true;
435     }
436
437     private PolicyDefinition setPolicyTargets(PolicyDefinition policyDefinition, Map<PolicyTargetType, List<String>> targets) {
438         policyDefinition.setTargets(targets);
439         return policyDefinition;
440     }
441
442     /**
443      * @param componentType the type of the component
444      * @param componentId   the id of the component which the policy resides under
445      * @param policyId      the id of the policy which its properties to return
446      * @param userId        the user id
447      * @return a list of policy properties or an error in a response format
448      */
449     public List<PropertyDataDefinition> getPolicyProperties(ComponentTypeEnum componentType, String componentId, String policyId, String userId) {
450         log.debug("#getPolicyProperties - fetching policy properties for component {} and policy {}", componentId, policyId);
451         try {
452             Component component = validateContainerComponentAndUserBeforeReadOperation(componentType, componentId, userId);
453             return getPolicyById(component, policyId).getProperties();
454         } finally {
455             janusGraphDao.commit();
456         }
457     }
458
459     /**
460      * Updates the policy properties of the component
461      *
462      * @param componentType the type of the component
463      * @param componentId   the id of the component which the policy resides under
464      * @param policyId      the id of the policy which its properties to return
465      * @param properties    a list of policy properties containing updated values
466      * @param userId        the user modifier id
467      * @param shouldLock    the flag defining if the component should be locked
468      * @return a list of policy properties or anerrorin a response format
469      */
470     public List<PropertyDataDefinition> updatePolicyProperties(ComponentTypeEnum componentType, String componentId, String policyId,
471                                                                PropertyDataDefinition[] properties, String userId, boolean shouldLock) {
472         List<PropertyDataDefinition> result;
473         Component component = null;
474         log.trace("#updatePolicyProperties - starting to update properties of the policy {} on the component {}. ", policyId, componentId);
475         boolean failed = true;
476         try {
477             component = validateAndLockComponentAndUserBeforeWriteOperation(componentType, componentId, userId, shouldLock);
478             failed = false;
479             result = setComponentValidateUpdatePolicyProperties(policyId, properties, component);
480         } finally {
481             if (shouldLock && !failed) {
482                 unlockComponent(failed, component);
483             }
484         }
485         return result;
486     }
487
488     @Override
489     public Either<List<PolicyDefinition>, ResponseFormat> declareProperties(String userId, String componentId, ComponentTypeEnum componentTypeEnum,
490                                                                             ComponentInstInputsMap componentInstInputsMap) {
491         return declarePropertiesToPolicies(userId, componentId, componentTypeEnum, componentInstInputsMap, true, false);
492     }
493
494     private Either<List<PolicyDefinition>, ResponseFormat> declarePropertiesToPolicies(String userId, String componentId,
495                                                                                        ComponentTypeEnum componentTypeEnum,
496                                                                                        ComponentInstInputsMap componentInstInputsMap,
497                                                                                        boolean shouldLock, boolean inTransaction) {
498         Either<List<PolicyDefinition>, ResponseFormat> result = null;
499         org.openecomp.sdc.be.model.Component component = null;
500         try {
501             validateUserExists(userId);
502             ComponentParametersView componentParametersView = new ComponentParametersView();
503             componentParametersView.disableAll();
504             componentParametersView.setIgnoreComponentInstances(false);
505             componentParametersView.setIgnoreComponentInstancesProperties(false);
506             componentParametersView.setIgnorePolicies(false);
507             componentParametersView.setIgnoreUsers(false);
508             component = validateComponentExists(componentId, componentTypeEnum, componentParametersView);
509             if (shouldLock) {
510                 lockComponent(component, DECLARE_PROPERTIES_TO_POLICIES);
511             }
512             validateCanWorkOnComponent(component, userId);
513             Either<List<PolicyDefinition>, StorageOperationStatus> declarePropertiesEither = propertyDeclarationOrchestrator
514                 .declarePropertiesToPolicies(component, componentInstInputsMap);
515             if (declarePropertiesEither.isRight()) {
516                 return Either.right(componentsUtils.getResponseFormat(declarePropertiesEither.right().value()));
517             }
518             result = Either.left(declarePropertiesEither.left().value());
519             return result;
520         } finally {
521             if (!inTransaction) {
522                 commitOrRollback(result);
523             }
524             // unlock resource
525             if (shouldLock && component != null) {
526                 graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType());
527             }
528         }
529     }
530
531     private List<PropertyDataDefinition> setComponentValidateUpdatePolicyProperties(String policyId, PropertyDataDefinition[] properties,
532                                                                                     Component component) {
533         Set<String> updatedPropertyNames = Arrays.stream(properties).map(PropertyDataDefinition::getName).collect(Collectors.toSet());
534         PolicyDefinition policyDefinition = validateAndUpdatePolicyProperties(component, policyId, properties);
535         return getFilteredProperties(policyDefinition.getProperties(), updatedPropertyNames);
536     }
537
538     private List<PropertyDataDefinition> getFilteredProperties(List<PropertyDataDefinition> all, Set<String> filtered) {
539         return all.stream().filter(pd -> filtered.contains(pd.getName())).collect(Collectors.toList());
540     }
541
542     private void unlockComponent(boolean shouldLock, boolean result, Component component) {
543         if (shouldLock && component != null) {
544             unlockComponent(result, component);
545         }
546     }
547
548     private void unlockComponent(boolean shouldLock, boolean result, Wrapper<Component> component) {
549         if (shouldLock && !component.isEmpty()) {
550             unlockComponent(result, component.getInnerElement());
551         }
552     }
553
554     private PolicyDefinition getPolicyById(Component component, String policyId) {
555         PolicyDefinition policyById = component.getPolicyById(policyId);
556         if (policyById == null) {
557             String cmptId = component.getUniqueId();
558             log.debug("#getPolicyById - policy with id {} does not exist on component with id {}", policyId, cmptId);
559             throw new ByActionStatusComponentException(ActionStatus.POLICY_NOT_FOUND_ON_CONTAINER, policyId, cmptId);
560         }
561         return policyById;
562     }
563
564     private PolicyDefinition createPolicy(String policyTypeName, Component component) {
565         PolicyTypeDefinition policyTypeDefinition = validatePolicyTypeOnCreatePolicy(policyTypeName, component);
566         return addPolicyToComponent(policyTypeDefinition, component);
567     }
568
569     private PolicyDefinition addPolicyToComponent(PolicyTypeDefinition policyType, Component component) {
570         Either<PolicyDefinition, StorageOperationStatus> associatePolicyToComponent = toscaOperationFacade
571             .associatePolicyToComponent(component.getUniqueId(), new PolicyDefinition(policyType), getNextPolicyCounter(component.getPolicies()));
572         if (associatePolicyToComponent.isRight()) {
573             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(associatePolicyToComponent.right().value()));
574         }
575         return associatePolicyToComponent.left().value();
576     }
577
578     private PolicyTypeDefinition validatePolicyTypeOnCreatePolicy(String policyTypeName, Component component) {
579         final var latestPolicyTypeByType = policyTypeOperation.getLatestPolicyTypeByType(policyTypeName, component.getModel());
580         if (latestPolicyTypeByType.isRight()) {
581             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(latestPolicyTypeByType.right().value()));
582         }
583         return validatePolicyTypeNotExcluded(latestPolicyTypeByType.left().value(), component);
584     }
585
586     private PolicyTypeDefinition validatePolicyTypeNotExcluded(PolicyTypeDefinition policyType, Component component) {
587         if (getExcludedPolicyTypesByComponent(component).contains(policyType.getType())) {
588             throw new ByActionStatusComponentException(ActionStatus.EXCLUDED_POLICY_TYPE, policyType.getType(),
589                 getComponentOrResourceTypeName(component));
590         }
591         return policyType;
592     }
593
594     private String getComponentOrResourceTypeName(Component component) {
595         return component.getComponentType() == ComponentTypeEnum.SERVICE ? ComponentTypeEnum.SERVICE.name()
596             : ((Resource) component).getResourceType().name();
597     }
598
599     private Component validateAndLockComponentAndUserBeforeWriteOperation(ComponentTypeEnum componentType, String componentId, String userId,
600                                                                           boolean shouldLock) {
601         Component component = validateContainerComponentAndUserBeforeReadOperation(componentType, componentId, userId);
602         validateComponentIsTopologyTemplate(component);
603         validateCanWorkOnComponent(component, userId);
604         lockComponent(component, shouldLock, "policyWritingOperation");
605         return component;
606     }
607
608     private Component validateComponentIsTopologyTemplate(Component component) {
609         if (!component.isTopologyTemplate()) {
610             log.error("#validateComponentIsTopologyTemplate - policy association to a component of Tosca type {} is not allowed. ",
611                 component.getToscaType());
612             throw new ByActionStatusComponentException(ActionStatus.RESOURCE_CANNOT_CONTAIN_POLICIES,
613                 "#validateAndLockComponentAndUserBeforeWriteOperation", component.getUniqueId(), component.getToscaType());
614         }
615         return component;
616     }
617
618     private Component validateContainerComponentAndUserBeforeReadOperation(ComponentTypeEnum componentType, String componentId, String userId) {
619         log.trace("#validateContainerComponentAndUserBeforeReadOperation - starting to validate the user {} before policy processing. ", userId);
620         validateUserExists(userId);
621         return validateComponentExists(componentType, componentId);
622     }
623
624     private Component validateComponentExists(ComponentTypeEnum componentType, String componentId) {
625         ComponentParametersView filter = new ComponentParametersView(true);
626         filter.setIgnorePolicies(false);
627         filter.setIgnoreUsers(false);
628         filter.setIgnoreComponentInstances(false);
629         filter.setIgnoreComponentInstancesAttributes(false);
630         filter.setIgnoreComponentInstancesProperties(false);
631         filter.setIgnoreGroups(false);
632         filter.setIgnoreInputs(false);
633         filter.setIgnoreProperties(false);
634         return validateComponentExists(componentId, componentType, filter);
635     }
636
637     private PolicyDefinition validateAndUpdatePolicy(Component component, PolicyDefinition policy) {
638         PolicyDefinition policyById = getPolicyById(component, policy.getUniqueId());
639         PolicyDefinition policyDefinition = validateUpdatePolicyBeforeUpdate(policy, policyById, component.getPolicies());
640         return updatePolicyOfComponent(component, policyDefinition);
641     }
642
643     private PolicyDefinition validateAndUpdatePolicyProperties(Component component, String policyId, PropertyDataDefinition[] properties) {
644         PolicyDefinition policyById = getPolicyById(component, policyId);
645         policyById = validateUpdatePolicyPropertiesBeforeUpdate(component, policyById, properties);
646         return updatePolicyOfComponent(component.getUniqueId(), policyById);
647     }
648
649     private PolicyDefinition updatePolicyOfComponent(String componentId, PolicyDefinition policy) {
650         return toscaOperationFacade.updatePolicyOfComponent(componentId, policy, PromoteVersionEnum.MINOR).left()
651             .on(ce -> componentExceptionPolicyDefinition(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(ce))));
652     }
653
654     private PolicyDefinition validateUpdatePolicyPropertiesBeforeUpdate(final Component policyOwnerComponent, PolicyDefinition policy, PropertyDataDefinition[] newProperties) {
655         if (CollectionUtils.isEmpty(policy.getProperties())) {
656             log.error(
657                 "#validateUpdatePolicyPropertiesBeforeUpdate - failed to update properites of the policy. Properties were not found on the policy. ");
658             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND);
659         }
660         return updatePropertyValues(policyOwnerComponent, policy, newProperties);
661     }
662
663     private PolicyDefinition updatePropertyValues(final Component policyOwnerComponent, PolicyDefinition policy, PropertyDataDefinition[] newProperties) {
664         Map<String, PropertyDataDefinition> oldProperties = policy.getProperties().stream()
665             .collect(toMap(PropertyDataDefinition::getName, Function.identity()));
666         for (PropertyDataDefinition newProperty : newProperties) {
667             if (!oldProperties.containsKey(newProperty.getName())) {
668                 log.error("#updatePropertyValues - failed to update properites of the policy {}. Properties were not found on the policy. ",
669                     policy.getName());
670                 throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, newProperty.getName());
671             }
672             final String newPropertyValueEither = updatePropertyValue(policyOwnerComponent, newProperty);
673             final PropertyDataDefinition currentProperty = oldProperties.get(newProperty.getName());
674             currentProperty.setValue(newPropertyValueEither);
675             currentProperty.setToscaFunction(newProperty.getToscaFunction());
676         }
677         return policy;
678     }
679
680     private <T extends PropertyDataDefinition> String updatePropertyValue(final Component policyOwnerComponent, final T property) {
681         Either<Object, Boolean> isValid = propertyOperation
682             .validateAndUpdatePropertyValue(policyOwnerComponent, property,
683                 componentsUtils.getAllDataTypes(applicationDataTypeCache, property.getModel())
684             );
685         if (isValid.isRight()) {
686             Boolean res = isValid.right().value();
687             if (Boolean.FALSE.equals(res)) {
688                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(
689                     DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
690             }
691         } else {
692             Object object = isValid.left().value();
693             if (object != null) {
694                 return object.toString();
695             }
696         }
697         return property.getValue();
698     }
699
700     private PolicyDefinition deletePolicy(Component component, String policyId) {
701         PolicyDefinition policyById = getPolicyById(component, policyId);
702         return removePolicyFromComponent(component, policyById);
703     }
704
705     private PolicyDefinition updatePolicyOfComponent(Component component, PolicyDefinition policy) {
706         Either<PolicyDefinition, StorageOperationStatus> updatePolicyRes = toscaOperationFacade
707             .updatePolicyOfComponent(component.getUniqueId(), policy, PromoteVersionEnum.MINOR);
708         if (updatePolicyRes.isRight()) {
709             log.error("#updatePolicyOfComponent - failed to update policy {} of the component {}. The status is {}. ", policy.getUniqueId(),
710                 component.getName(), updatePolicyRes.right().value());
711             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(updatePolicyRes.right().value()));
712         } else {
713             log.trace("#updatePolicyOfComponent - the policy with the name {} was updated. ", updatePolicyRes.left().value().getName());
714             return updatePolicyRes.left().value();
715         }
716     }
717
718     private PolicyDefinition removePolicyFromComponent(Component component, PolicyDefinition policy) {
719         StorageOperationStatus updatePolicyStatus = toscaOperationFacade.removePolicyFromComponent(component.getUniqueId(), policy.getUniqueId());
720         if (updatePolicyStatus != StorageOperationStatus.OK) {
721             log.error("#removePolicyFromComponent - failed to remove policy {} from the component {}. The status is {}. ", policy.getUniqueId(),
722                 component.getName(), updatePolicyStatus);
723             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(updatePolicyStatus));
724         } else {
725             log.trace("#removePolicyFromComponent - the policy with the name {} was deleted. ", updatePolicyStatus);
726             return policy;
727         }
728     }
729
730     private PolicyDefinition validateUpdatePolicyBeforeUpdate(PolicyDefinition recievedPolicy, PolicyDefinition oldPolicy,
731                                                               Map<String, PolicyDefinition> policies) {
732         Either<PolicyDefinition, ActionStatus> policyDefinitionActionStatusEither = validatePolicyFields(recievedPolicy,
733             new PolicyDefinition(oldPolicy), policies);
734         if (policyDefinitionActionStatusEither.isRight()) {
735             throw new ByActionStatusComponentException(policyDefinitionActionStatusEither.right().value(), recievedPolicy.getName());
736         }
737         return policyDefinitionActionStatusEither.left().value();
738     }
739
740     private PolicyDefinition updateTargets(String componentId, PolicyDefinition policy, Map<PolicyTargetType, List<String>> targets,
741                                            String policyId) {
742         if (policy == null) {
743             throw new ByActionStatusComponentException(ActionStatus.POLICY_NOT_FOUND_ON_CONTAINER, policyId, componentId);
744         }
745         PolicyDefinition updatedPolicy = setPolicyTargets(policy, targets);
746         return updatePolicyOfComponent(componentId, updatedPolicy);
747     }
748 }