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