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