Fix instance declared inputs mapped to substitution mapping
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / property / PropertyDeclarationOrchestrator.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 package org.openecomp.sdc.be.components.property;
21
22 import static org.apache.commons.collections.MapUtils.isNotEmpty;
23
24 import fj.data.Either;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
30 import org.apache.commons.collections.CollectionUtils;
31 import org.apache.commons.collections.MapUtils;
32 import org.apache.commons.lang3.tuple.Pair;
33 import org.openecomp.sdc.be.components.property.propertytopolicydeclarators.ComponentInstancePropertyToPolicyDeclarator;
34 import org.openecomp.sdc.be.components.property.propertytopolicydeclarators.ComponentPropertyToPolicyDeclarator;
35 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
36 import org.openecomp.sdc.be.model.Component;
37 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
38 import org.openecomp.sdc.be.model.ComponentInstancePropInput;
39 import org.openecomp.sdc.be.model.InputDefinition;
40 import org.openecomp.sdc.be.model.PolicyDefinition;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43
44 @org.springframework.stereotype.Component("propertyDeclarationOrchestrator")
45 public class PropertyDeclarationOrchestrator {
46
47     private static final Logger log = Logger.getLogger(PropertyDeclarationOrchestrator.class);
48     private ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator;
49     private ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator;
50     private PolicyPropertyDeclarator policyPropertyDeclarator;
51     private GroupPropertyDeclarator groupPropertyDeclarator;
52     private ComponentPropertyDeclarator servicePropertyDeclarator;
53     private List<PropertyDeclarator> propertyDeclaratorsToInput;
54     private List<PropertyDeclarator> propertyDeclaratorsToPolicy;
55     private ComponentPropertyToPolicyDeclarator componentPropertyToPolicyDeclarator;
56     private ComponentInstancePropertyToPolicyDeclarator componentInstancePropertyToPolicyDeclarator;
57
58     public PropertyDeclarationOrchestrator(ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator,
59                                            ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator,
60                                            PolicyPropertyDeclarator policyPropertyDeclarator, GroupPropertyDeclarator groupPropertyDeclarator,
61                                            ComponentPropertyDeclarator servicePropertyDeclarator,
62                                            ComponentPropertyToPolicyDeclarator componentPropertyToPolicyDeclarator,
63                                            ComponentInstancePropertyToPolicyDeclarator componentInstancePropertyToPolicyDeclarator) {
64         this.componentInstanceInputPropertyDeclarator = componentInstanceInputPropertyDeclarator;
65         this.componentInstancePropertyDeclarator = componentInstancePropertyDeclarator;
66         this.policyPropertyDeclarator = policyPropertyDeclarator;
67         this.groupPropertyDeclarator = groupPropertyDeclarator;
68         this.servicePropertyDeclarator = servicePropertyDeclarator;
69         this.componentPropertyToPolicyDeclarator = componentPropertyToPolicyDeclarator;
70         this.componentInstancePropertyToPolicyDeclarator = componentInstancePropertyToPolicyDeclarator;
71         propertyDeclaratorsToInput = Arrays
72             .asList(componentInstanceInputPropertyDeclarator, componentInstancePropertyDeclarator, policyPropertyDeclarator, groupPropertyDeclarator,
73                 servicePropertyDeclarator);
74         propertyDeclaratorsToPolicy = Arrays.asList(componentPropertyToPolicyDeclarator, componentInstancePropertyToPolicyDeclarator);
75     }
76
77     public Either<List<InputDefinition>, StorageOperationStatus> declarePropertiesToInputs(Component component,
78                                                                                            ComponentInstInputsMap componentInstInputsMap) {
79         updatePropertiesConstraints(component, componentInstInputsMap);
80         PropertyDeclarator propertyDeclarator = getPropertyDeclarator(componentInstInputsMap);
81         undoCISubstitutionMapping(componentInstInputsMap);
82         Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
83         return propertyDeclarator.declarePropertiesAsInputs(component, propsToDeclare.getLeft(), propsToDeclare.getRight());
84     }
85
86     private void undoCISubstitutionMapping(ComponentInstInputsMap componentInstInputsMap) {
87         if (MapUtils.isNotEmpty(componentInstInputsMap.getComponentInstanceProperties())) {
88             componentInstInputsMap.getComponentInstanceProperties().values()
89                 .forEach(componentInstancePropInputsList -> componentInstancePropInputsList.stream()
90                     .forEach(componentInstancePropInput -> componentInstancePropInput.setMappedToComponentProperty(false)));
91         }
92     }
93
94     private void updatePropertiesConstraints(Component component, ComponentInstInputsMap componentInstInputsMap) {
95         componentInstInputsMap.getComponentInstanceProperties()
96             .forEach((k, v) -> updatePropsConstraints(component.safeGetComponentInstancesProperties(), k, v));
97         componentInstInputsMap.getComponentInstanceInputsMap()
98             .forEach((k, v) -> updatePropsConstraints(component.safeGetComponentInstancesInputs(), k, v));
99         componentInstInputsMap.getGroupProperties().forEach((k, v) -> updatePropsConstraints(component.safeGetPolicyProperties(), k, v));
100         componentInstInputsMap.getPolicyProperties().forEach((k, v) -> updatePropsConstraints(component.safeGetGroupsProperties(), k, v));
101     }
102
103     public Either<List<PolicyDefinition>, StorageOperationStatus> declarePropertiesToPolicies(Component component,
104                                                                                               ComponentInstInputsMap componentInstInputsMap) {
105         PropertyDeclarator propertyDeclarator = getPropertyDeclarator(componentInstInputsMap);
106         Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
107         return propertyDeclarator.declarePropertiesAsPolicies(component, propsToDeclare.getLeft(), propsToDeclare.getRight());
108     }
109
110     public Either<InputDefinition, StorageOperationStatus> declarePropertiesToListInput(Component component,
111                                                                                         ComponentInstInputsMap componentInstInputsMap,
112                                                                                         InputDefinition input) {
113         PropertyDeclarator propertyDeclarator = getPropertyDeclarator(componentInstInputsMap);
114         Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
115         log.debug("#declarePropertiesToInputs: componentId={}, propOwnerId={}", component.getUniqueId(), propsToDeclare.getLeft());
116         return propertyDeclarator.declarePropertiesAsListInput(component, propsToDeclare.getLeft(), propsToDeclare.getRight(), input);
117     }
118
119     private <T extends PropertyDataDefinition> void updatePropsConstraints(Map<String, List<T>> instancesProperties, String ownerId,
120                                                                            List<ComponentInstancePropInput> inputs) {
121         Optional<List<T>> propertiesOpt = instancesProperties.entrySet().stream().filter(e -> e.getKey().equals(ownerId)).map(Map.Entry::getValue)
122             .findFirst();
123         if (propertiesOpt.isPresent()) {
124             Map<String, PropertyDataDefinition> instProps = propertiesOpt.get().stream()
125                 .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
126             inputs.stream().filter(i -> instProps.containsKey(i.getName())).forEach(i -> updatePropConstraints(i, instProps.get(i.getName())));
127         }
128     }
129
130     private void updatePropConstraints(PropertyDataDefinition input, PropertyDataDefinition property) {
131         if (CollectionUtils.isNotEmpty(property.getPropertyConstraints())) {
132             input.setPropertyConstraints(property.getPropertyConstraints());
133         } else if (property.getSchemaProperty() != null && CollectionUtils.isNotEmpty(property.getSchemaProperty().getPropertyConstraints())) {
134             input.setPropertyConstraints(property.getSchemaProperty().getPropertyConstraints());
135         }
136     }
137
138     public StorageOperationStatus unDeclarePropertiesAsInputs(Component component, InputDefinition inputToDelete) {
139         log.debug("#unDeclarePropertiesAsInputs - removing input declaration for input {} on component {}", inputToDelete.getName(),
140             component.getUniqueId());
141         for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) {
142             StorageOperationStatus storageOperationStatus = propertyDeclarator.unDeclarePropertiesAsInputs(component, inputToDelete);
143             if (StorageOperationStatus.OK != storageOperationStatus) {
144                 log.debug("#unDeclarePropertiesAsInputs - failed to remove input declaration for input {} on component {}. reason {}",
145                     inputToDelete.getName(), component.getUniqueId(), storageOperationStatus);
146                 return storageOperationStatus;
147             }
148         }
149         return StorageOperationStatus.OK;
150     }
151
152     /**
153      * Un declare properties declared as list type input
154      *
155      * @param component
156      * @param inputToDelete
157      * @return
158      */
159     public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputToDelete) {
160         log.debug("#unDeclarePropertiesAsListInputs - removing input declaration for input {} on component {}", inputToDelete.getName(),
161             component.getUniqueId());
162         for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) {
163             StorageOperationStatus storageOperationStatus = propertyDeclarator.unDeclarePropertiesAsListInputs(component, inputToDelete);
164             if (StorageOperationStatus.OK != storageOperationStatus) {
165                 log.debug("#unDeclarePropertiesAsListInputs - failed to remove input declaration for input {} on component {}. reason {}",
166                     inputToDelete.getName(), component.getUniqueId(), storageOperationStatus);
167                 return storageOperationStatus;
168             }
169         }
170         return StorageOperationStatus.OK;
171     }
172
173     /**
174      * Get properties owner id
175      *
176      * @param componentInstInputsMap
177      * @return
178      */
179     public String getPropOwnerId(ComponentInstInputsMap componentInstInputsMap) {
180         Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
181         return propsToDeclare.getLeft();
182     }
183
184     public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policyToDelete) {
185         log.debug("#unDeclarePropertiesAsInputs - removing policy declaration for input {} on component {}", policyToDelete.getName(),
186             component.getUniqueId());
187         for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToPolicy) {
188             StorageOperationStatus storageOperationStatus = propertyDeclarator.unDeclarePropertiesAsPolicies(component, policyToDelete);
189             if (StorageOperationStatus.OK != storageOperationStatus) {
190                 log.debug("#unDeclarePropertiesAsInputs - failed to remove policy declaration for policy {} on component {}. reason {}",
191                     policyToDelete.getName(), component.getUniqueId(), storageOperationStatus);
192                 return storageOperationStatus;
193             }
194         }
195         return StorageOperationStatus.OK;
196     }
197
198     private PropertyDeclarator getPropertyDeclarator(ComponentInstInputsMap componentInstInputsMap) {
199         if (isNotEmpty(componentInstInputsMap.getComponentInstanceInputsMap())) {
200             return componentInstanceInputPropertyDeclarator;
201         }
202         if (isNotEmpty(componentInstInputsMap.getComponentInstanceProperties())) {
203             return componentInstancePropertyDeclarator;
204         }
205         if (isNotEmpty(componentInstInputsMap.getPolicyProperties())) {
206             return policyPropertyDeclarator;
207         }
208         if (isNotEmpty(componentInstInputsMap.getGroupProperties())) {
209             return groupPropertyDeclarator;
210         }
211         if (isNotEmpty(componentInstInputsMap.getServiceProperties())) {
212             return servicePropertyDeclarator;
213         }
214         if (isNotEmpty(componentInstInputsMap.getComponentPropertiesToPolicies())) {
215             return componentPropertyToPolicyDeclarator;
216         }
217         if (isNotEmpty(componentInstInputsMap.getComponentInstancePropertiesToPolicies())) {
218             return componentInstancePropertyToPolicyDeclarator;
219         }
220         throw new IllegalStateException("there are no properties selected for declaration");
221     }
222 }