649f083903385a332367c467e6aac286bfb4e45d
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / CapabiltyRequirementConvertor.java
1 /*-
2
3  * ============LICENSE_START=======================================================
4  * SDC
5  * ================================================================================
6  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.sdc.be.tosca;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.stream.Collectors;
29
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
32 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
33 import org.openecomp.sdc.be.model.CapabilityDefinition;
34 import org.openecomp.sdc.be.model.Component;
35 import org.openecomp.sdc.be.model.ComponentInstance;
36 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
37 import org.openecomp.sdc.be.model.DataTypeDefinition;
38 import org.openecomp.sdc.be.model.PropertyDefinition;
39 import org.openecomp.sdc.be.model.RequirementDefinition;
40 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
41 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
42 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
43 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
44 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
45 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
46 import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
47 import org.openecomp.sdc.common.util.ValidationUtils;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import com.google.common.collect.Lists;
52
53 import fj.data.Either;
54
55 public class CapabiltyRequirementConvertor {
56         private static CapabiltyRequirementConvertor instance;
57         public final static String PATH_DELIMITER = ".";
58         
59         protected CapabiltyRequirementConvertor() {
60
61         }
62
63         public static synchronized CapabiltyRequirementConvertor getInstance() {
64                 if (instance == null) {
65                         instance = new CapabiltyRequirementConvertor();
66                 }
67                 return instance;
68         }
69
70         private static Logger log = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName());
71
72         public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
73
74                 Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
75                 if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
76                         Map<String, ToscaTemplateCapability> capabilties = new HashMap<>();
77                         capabilitiesInst.entrySet().forEach(e -> {
78                                 List<CapabilityDefinition> capList = e.getValue();
79                                 if (capList != null && !capList.isEmpty()) {
80                                         capList.forEach(c -> {
81                                                 convertOverridenProperties(componentInstance, dataTypes, capabilties, c);
82                                         });
83                                 }
84                         });
85                         if (capabilties != null && !capabilties.isEmpty()) {
86                                 nodeTemplate.setCapabilities(capabilties);
87                         }
88                 }
89                 return Either.left(nodeTemplate);
90         }
91
92         private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c) {
93                 List<ComponentInstanceProperty> properties = c.getProperties();
94                 if (properties != null && !properties.isEmpty()) {
95                         properties.stream().filter(p -> (p.getValueUniqueUid() != null)).forEach(p -> {
96                                 convertOverridenProperty(componentInstance, dataTypes, capabilties, c, p);
97                         });
98                 }
99         }
100
101         private void convertOverridenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c, ComponentInstanceProperty p) {
102                 if (log.isDebugEnabled()) {
103                         log.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), c.getName(), p.getValue());
104                 }
105                 ToscaTemplateCapability toscaTemplateCapability = capabilties.get(c.getName());
106                 if (toscaTemplateCapability == null) {
107                         toscaTemplateCapability = new ToscaTemplateCapability();
108                         capabilties.put(c.getName(), toscaTemplateCapability);
109                 }
110                 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
111                 if (toscaCapProp == null) {
112                         toscaCapProp = new HashMap<>();
113                 }
114                 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
115                 toscaCapProp.put(p.getName(), convertedValue);
116                 toscaTemplateCapability.setProperties(toscaCapProp);
117         }
118
119         private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
120                 log.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
121                 String propertyType = prop.getType();
122                 String innerType = null;
123                 if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
124                         innerType = prop.getSchema().getProperty().getType();
125                 }
126                 Object convertedValue = PropertyConvertor.getInstance().convertToToscaObject(propertyType,  prop.getValue(), innerType, dataTypes);
127                 return convertedValue;
128         }
129
130         public Either<ToscaNodeType, ToscaError> convertRequirements(Component component, ToscaNodeType nodeType) {
131                 List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(component);
132                 if (!toscaRequirements.isEmpty()) {
133                         nodeType.setRequirements(toscaRequirements);
134                 }
135                 log.debug("Finish convert Requirements for node type");
136
137                 return Either.left(nodeType);
138         }
139
140         public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Component component, SubstitutionMapping substitutionMapping) {
141                 Map<String, String[]> toscaRequirements = convertSubstitutionMappingRequirementsAsMap(component);
142                 if (!toscaRequirements.isEmpty()) {
143                         substitutionMapping.setRequirements(toscaRequirements);
144                 }
145                 log.debug("Finish convert Requirements for node type");
146
147                 return Either.left(substitutionMapping);
148         }
149
150         private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Component component) {
151                 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
152                 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
153                 if (requirements != null) {
154                         boolean isNodeType = ToscaUtils.isAtomicType(component);
155                         for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
156                                 entry.getValue().stream().filter(r -> (!isNodeType || (isNodeType && component.getUniqueId().equals(r.getOwnerId())) || (isNodeType && r.getOwnerId() == null))).forEach(r -> {
157                                         ImmutablePair<String, ToscaRequirement> pair = convertRequirement(component, isNodeType, r);
158                                         Map<String, ToscaRequirement> requirement = new HashMap<>();
159
160                                         requirement.put(pair.left, pair.right);
161                                         toscaRequirements.add(requirement);
162                                 });
163
164                                 log.debug("Finish convert Requirements for node type");
165                         }
166                 } else {
167                         log.debug("No Requirements for node type");
168                 }
169                 return toscaRequirements;
170         }
171
172         private String getSubPathByFirstDelimiterAppearance(String path) {
173                 return path.substring(path.indexOf(PATH_DELIMITER) + 1);
174         }
175         
176         private String getSubPathByLastDelimiterAppearance(String path) {
177                 return path.substring(path.lastIndexOf(PATH_DELIMITER) + 1);
178         }
179         
180         //This function calls on Substitution Mapping region - the component is always non-atomic
181         private Map<String, String[]> convertSubstitutionMappingRequirementsAsMap(Component component) {
182                 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
183                 Map<String,  String[]> toscaRequirements = new HashMap<>();
184                 if (requirements != null) {
185                         for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
186                                 entry.getValue().stream().forEach(r -> {
187                                         String fullReqName;
188                                         String sourceCapName;
189                                         if(ToscaUtils.isComplexVfc(component)){
190                                                 fullReqName = r.getName();
191                                                 sourceCapName = r.getParentName();
192                                         } else {
193                                                 fullReqName = getRequirementPath(r);
194                                                 sourceCapName = getSubPathByFirstDelimiterAppearance(fullReqName);
195                                         }
196                                         log.debug("the requirement {} belongs to resource {} ", fullReqName, component.getUniqueId());
197                                         if(sourceCapName!= null){
198                                                 toscaRequirements.put(fullReqName, new String[]{r.getOwnerName(), sourceCapName});
199                                         }
200                                 });
201                                 log.debug("Finish convert Requirements for node type");
202                         }
203                 } else {
204                         log.debug("No Requirements for node type");
205                 }
206                 return toscaRequirements;
207         }
208
209         private String getRequirementPath(RequirementDefinition r) {
210                 List<String> pathArray = Lists.reverse(r.getPath().stream()
211                                 .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path)))
212                                 .collect(Collectors.toList()));
213                 return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(r.getName()).toString();
214                 
215         }
216         
217         private ImmutablePair<String, ToscaRequirement> convertRequirement(Component component, boolean isNodeType, RequirementDefinition r) {
218                 String name = r.getName();
219                 if (!isNodeType) {
220                         name = getRequirementPath(r);
221                 }
222                 log.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
223                 ToscaRequirement toscaRequirement = new ToscaRequirement();
224
225                 List<Object> occurences = new ArrayList<>();
226                 occurences.add(Integer.valueOf(r.getMinOccurrences()));
227                 if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
228                         occurences.add(r.getMaxOccurrences());
229                 } else {
230                         occurences.add(Integer.valueOf(r.getMaxOccurrences()));
231                 }
232                 toscaRequirement.setOccurrences(occurences);
233                 // toscaRequirement.setOccurrences(createOcurrencesRange(requirementDefinition.getMinOccurrences(),
234                 // requirementDefinition.getMaxOccurrences()));
235                 toscaRequirement.setNode(r.getNode());
236                 toscaRequirement.setCapability(r.getCapability());
237                 toscaRequirement.setRelationship(r.getRelationship());
238
239                 ImmutablePair<String, ToscaRequirement> pair = new ImmutablePair<String, ToscaRequirement>(name, toscaRequirement);
240                 return pair;
241         }
242
243         public Map<String, ToscaCapability> convertCapabilities(Component component, Map<String, DataTypeDefinition> dataTypes) {
244                 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
245                 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
246                 if (capabilities != null) {
247                         boolean isNodeType = ToscaUtils.isAtomicType(component);
248                         for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
249                                 entry.getValue().stream().filter(c -> (!isNodeType || (isNodeType && component.getUniqueId().equals(c.getOwnerId())) || (isNodeType && c.getOwnerId() == null) )).forEach(c -> {
250                                         convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes);
251
252                                 });
253                         }
254                 } else {
255                         log.debug("No Capabilities for node type");
256                 }
257
258                 return toscaCapabilities;
259         }
260         
261         //This function calls on Substitution Mapping region - the component is always non-atomic
262         public Map<String, String[]> convertSubstitutionMappingCapabilities(Component component, Map<String, DataTypeDefinition> dataTypes) {
263                 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
264                 Map<String, String[]> toscaCapabilities = new HashMap<>();
265                 if (capabilities != null) {
266                         for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
267                                 entry.getValue().stream().forEach(c -> {
268                                         String fullCapName;
269                                         String sourceReqName;
270                                         if(ToscaUtils.isComplexVfc(component)){
271                                                 fullCapName = c.getName();
272                                                 sourceReqName = c.getParentName();
273                                         } else {
274                                                 fullCapName = getCapabilityPath(c);
275                                                 sourceReqName = getSubPathByFirstDelimiterAppearance(fullCapName);
276                                         }
277                                         log.debug("the capabilty {} belongs to resource {} ", fullCapName, component.getUniqueId());
278                                         if(sourceReqName!= null){
279                                                 toscaCapabilities.put(fullCapName, new String[]{c.getOwnerName(), sourceReqName});
280                                         }
281                                 });
282                         }
283                 } else {
284                         log.debug("No Capabilities for node type");
285                 }
286
287                 return toscaCapabilities;
288         }
289         
290         private String getCapabilityPath(CapabilityDefinition c)  {
291                 List<String> pathArray = Lists.reverse(c.getPath().stream()
292                                 .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path)))
293                                 .collect(Collectors.toList()));
294                 return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(c.getName()).toString();
295         }
296         
297         
298         
299         private void convertCapabilty(Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes) {
300                 String name = c.getName();
301                 if (!isNodeType) {
302                         name = getCapabilityPath(c);
303                 }
304                 log.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId());
305                 ToscaCapability toscaCapability = new ToscaCapability();
306                 toscaCapability.setDescription(c.getDescription());
307                 toscaCapability.setType(c.getType());
308
309                 List<Object> occurences = new ArrayList<>();
310                 occurences.add(Integer.valueOf(c.getMinOccurrences()));
311                 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
312                         occurences.add(c.getMaxOccurrences());
313                 } else {
314                         occurences.add(Integer.valueOf(c.getMaxOccurrences()));
315                 }
316                 toscaCapability.setOccurrences(occurences);
317
318                 toscaCapability.setValid_source_types(c.getValidSourceTypes());
319                 List<ComponentInstanceProperty> properties = c.getProperties();
320                 if (properties != null && !properties.isEmpty()) {
321                         Map<String, ToscaProperty> toscaProperties = new HashMap<>();
322                         for (PropertyDefinition property : properties) {
323                                 ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
324                                 toscaProperties.put(property.getName(), toscaProperty);
325                         }
326                         toscaCapability.setProperties(toscaProperties);
327                 }
328                 toscaCapabilities.put(name, toscaCapability);
329         }
330
331 }