3 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.openecomp.sdc.be.tosca;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.stream.Collectors;
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;
51 import com.google.common.collect.Lists;
53 import fj.data.Either;
55 public class CapabiltyRequirementConvertor {
56 private static CapabiltyRequirementConvertor instance;
57 public final static String PATH_DELIMITER = ".";
59 protected CapabiltyRequirementConvertor() {
63 public static synchronized CapabiltyRequirementConvertor getInstance() {
64 if (instance == null) {
65 instance = new CapabiltyRequirementConvertor();
70 private static Logger log = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName());
72 public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
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);
85 if (capabilties != null && !capabilties.isEmpty()) {
86 nodeTemplate.setCapabilities(capabilties);
89 return Either.left(nodeTemplate);
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);
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());
105 ToscaTemplateCapability toscaTemplateCapability = capabilties.get(c.getName());
106 if (toscaTemplateCapability == null) {
107 toscaTemplateCapability = new ToscaTemplateCapability();
108 capabilties.put(c.getName(), toscaTemplateCapability);
110 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
111 if (toscaCapProp == null) {
112 toscaCapProp = new HashMap<>();
114 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
115 toscaCapProp.put(p.getName(), convertedValue);
116 toscaTemplateCapability.setProperties(toscaCapProp);
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();
126 Object convertedValue = PropertyConvertor.getInstance().convertToToscaObject(propertyType, prop.getValue(), innerType, dataTypes);
127 return convertedValue;
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);
135 log.debug("Finish convert Requirements for node type");
137 return Either.left(nodeType);
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);
145 log.debug("Finish convert Requirements for node type");
147 return Either.left(substitutionMapping);
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<>();
160 requirement.put(pair.left, pair.right);
161 toscaRequirements.add(requirement);
164 log.debug("Finish convert Requirements for node type");
167 log.debug("No Requirements for node type");
169 return toscaRequirements;
172 private String getSubPathByFirstDelimiterAppearance(String path) {
173 return path.substring(path.indexOf(PATH_DELIMITER) + 1);
176 private String getSubPathByLastDelimiterAppearance(String path) {
177 return path.substring(path.lastIndexOf(PATH_DELIMITER) + 1);
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 -> {
188 String sourceCapName;
189 if(ToscaUtils.isComplexVfc(component)){
190 fullReqName = r.getName();
191 sourceCapName = r.getParentName();
193 fullReqName = getRequirementPath(r);
194 sourceCapName = getSubPathByFirstDelimiterAppearance(fullReqName);
196 log.debug("the requirement {} belongs to resource {} ", fullReqName, component.getUniqueId());
197 if(sourceCapName!= null){
198 toscaRequirements.put(fullReqName, new String[]{r.getOwnerName(), sourceCapName});
201 log.debug("Finish convert Requirements for node type");
204 log.debug("No Requirements for node type");
206 return toscaRequirements;
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();
217 private ImmutablePair<String, ToscaRequirement> convertRequirement(Component component, boolean isNodeType, RequirementDefinition r) {
218 String name = r.getName();
220 name = getRequirementPath(r);
222 log.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
223 ToscaRequirement toscaRequirement = new ToscaRequirement();
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());
230 occurences.add(Integer.valueOf(r.getMaxOccurrences()));
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());
239 ImmutablePair<String, ToscaRequirement> pair = new ImmutablePair<String, ToscaRequirement>(name, toscaRequirement);
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);
255 log.debug("No Capabilities for node type");
258 return toscaCapabilities;
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 -> {
269 String sourceReqName;
270 if(ToscaUtils.isComplexVfc(component)){
271 fullCapName = c.getName();
272 sourceReqName = c.getParentName();
274 fullCapName = getCapabilityPath(c);
275 sourceReqName = getSubPathByFirstDelimiterAppearance(fullCapName);
277 log.debug("the capabilty {} belongs to resource {} ", fullCapName, component.getUniqueId());
278 if(sourceReqName!= null){
279 toscaCapabilities.put(fullCapName, new String[]{c.getOwnerName(), sourceReqName});
284 log.debug("No Capabilities for node type");
287 return toscaCapabilities;
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();
299 private void convertCapabilty(Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes) {
300 String name = c.getName();
302 name = getCapabilityPath(c);
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());
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());
314 occurences.add(Integer.valueOf(c.getMaxOccurrences()));
316 toscaCapability.setOccurrences(occurences);
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);
326 toscaCapability.setProperties(toscaProperties);
328 toscaCapabilities.put(name, toscaCapability);