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