2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.openecomp.sdc.be.tosca;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.collections.MapUtils.isNotEmpty;
24 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
25 import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
30 import fj.data.Either;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.LinkedHashMap;
38 import java.util.LinkedHashSet;
39 import java.util.List;
41 import java.util.Map.Entry;
42 import java.util.Objects;
43 import java.util.Optional;
45 import java.util.function.Supplier;
46 import java.util.stream.Collectors;
47 import lombok.NoArgsConstructor;
48 import org.apache.commons.collections.CollectionUtils;
49 import org.apache.commons.collections.MapUtils;
50 import org.apache.commons.lang.StringUtils;
51 import org.apache.commons.lang3.tuple.ImmutablePair;
52 import org.apache.commons.lang3.tuple.ImmutableTriple;
53 import org.apache.commons.lang3.tuple.Triple;
54 import org.onap.sdc.tosca.services.YamlUtil;
55 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
56 import org.openecomp.sdc.be.config.ConfigurationManager;
57 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
58 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
59 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
60 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
69 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
70 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
71 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
73 import org.openecomp.sdc.be.exception.ToscaExportException;
74 import org.openecomp.sdc.be.model.ArtifactDefinition;
75 import org.openecomp.sdc.be.model.AttributeDefinition;
76 import org.openecomp.sdc.be.model.CapabilityDefinition;
77 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
78 import org.openecomp.sdc.be.model.Component;
79 import org.openecomp.sdc.be.model.ComponentInstance;
80 import org.openecomp.sdc.be.model.ComponentInstanceInput;
81 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
82 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
83 import org.openecomp.sdc.be.model.ComponentParametersView;
84 import org.openecomp.sdc.be.model.DataTypeDefinition;
85 import org.openecomp.sdc.be.model.GroupInstance;
86 import org.openecomp.sdc.be.model.InputDefinition;
87 import org.openecomp.sdc.be.model.InterfaceDefinition;
88 import org.openecomp.sdc.be.model.PropertyDefinition;
89 import org.openecomp.sdc.be.model.RelationshipInfo;
90 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
91 import org.openecomp.sdc.be.model.RequirementDefinition;
92 import org.openecomp.sdc.be.model.Resource;
93 import org.openecomp.sdc.be.model.Service;
94 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
95 import org.openecomp.sdc.be.model.category.CategoryDefinition;
96 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
97 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
98 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
99 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
100 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
101 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
102 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
103 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
104 import org.openecomp.sdc.be.tosca.model.NodeFilter;
105 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
106 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
107 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
108 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
109 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
110 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
111 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
112 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
113 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
114 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
115 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
116 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
117 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
118 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
119 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
120 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
121 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
122 import org.openecomp.sdc.be.tosca.utils.InputConverter;
123 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
124 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
125 import org.openecomp.sdc.common.log.wrappers.Logger;
126 import org.springframework.beans.factory.annotation.Autowired;
127 import org.yaml.snakeyaml.DumperOptions;
128 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
129 import org.yaml.snakeyaml.Yaml;
130 import org.yaml.snakeyaml.introspector.BeanAccess;
131 import org.yaml.snakeyaml.introspector.Property;
132 import org.yaml.snakeyaml.introspector.PropertyUtils;
133 import org.yaml.snakeyaml.nodes.MappingNode;
134 import org.yaml.snakeyaml.nodes.Node;
135 import org.yaml.snakeyaml.nodes.NodeTuple;
136 import org.yaml.snakeyaml.nodes.Tag;
137 import org.yaml.snakeyaml.representer.Represent;
138 import org.yaml.snakeyaml.representer.Representer;
141 @org.springframework.stereotype.Component("tosca-export-handler")
142 public class ToscaExportHandler {
144 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
145 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
146 private static final String INVARIANT_UUID = "invariantUUID";
147 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
148 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
149 private static final String IMPORTS_FILE_KEY = "file";
150 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
151 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
152 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
153 private static final String NATIVE_ROOT = "tosca.nodes.Root";
154 private static final YamlUtil yamlUtil = new YamlUtil();
155 private ApplicationDataTypeCache dataTypeCache;
156 private ToscaOperationFacade toscaOperationFacade;
157 private CapabilityRequirementConverter capabilityRequirementConverter;
158 private PolicyExportParser policyExportParser;
159 private GroupExportParser groupExportParser;
160 private PropertyConvertor propertyConvertor;
161 private InputConverter inputConverter;
162 private OutputConverter outputConverter;
163 private InterfaceLifecycleOperation interfaceLifecycleOperation;
164 private InterfacesOperationsConverter interfacesOperationsConverter;
167 public ToscaExportHandler(final ApplicationDataTypeCache dataTypeCache, final ToscaOperationFacade toscaOperationFacade,
168 final CapabilityRequirementConverter capabilityRequirementConverter, final PolicyExportParser policyExportParser,
169 final GroupExportParser groupExportParser, final PropertyConvertor propertyConvertor,
170 final InputConverter inputConverter, final OutputConverter outputConverter,
171 final InterfaceLifecycleOperation interfaceLifecycleOperation,
172 final InterfacesOperationsConverter interfacesOperationsConverter) {
173 this.dataTypeCache = dataTypeCache;
174 this.toscaOperationFacade = toscaOperationFacade;
175 this.capabilityRequirementConverter = capabilityRequirementConverter;
176 this.policyExportParser = policyExportParser;
177 this.groupExportParser = groupExportParser;
178 this.propertyConvertor = propertyConvertor;
179 this.inputConverter = inputConverter;
180 this.outputConverter = outputConverter;
181 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
182 this.interfacesOperationsConverter = interfacesOperationsConverter;
185 public static String getInterfaceFilename(String artifactName) {
186 return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME;
189 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
190 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
193 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
194 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
197 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
198 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
201 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
202 final List<Map<String, Map<String, String>>> imports = getDefaultToscaImportConfig();
203 if (CollectionUtils.isEmpty(imports)) {
204 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
205 return Either.right(ToscaError.GENERAL_ERROR);
207 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
208 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType().startsWith("org.openecomp.resource.abstract.nodes.")) {
209 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade.getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion());
210 if (baseType.isLeft() && baseType.left().value() != null) {
211 addDependencies(imports, dependencies , baseType.left().value());
213 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
217 String toscaVersion = null;
218 if (component instanceof Resource) {
219 toscaVersion = ((Resource) component).getToscaVersion();
221 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
222 toscaTemplate.setImports(new ArrayList<>(imports));
223 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
224 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
225 isAssociatedComponent);
226 if (toscaTemplateRes.isRight()) {
227 return Either.right(toscaTemplateRes.right().value());
229 toscaTemplate = toscaTemplateRes.left().value();
230 toscaTemplate.setDependencies(dependencies);
231 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
232 return Either.left(toscaRepresentation);
235 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
236 CustomRepresenter representer = new CustomRepresenter();
237 DumperOptions options = new DumperOptions();
238 options.setAllowReadOnlyProperties(false);
239 options.setPrettyFlow(true);
240 options.setDefaultFlowStyle(FlowStyle.FLOW);
241 options.setCanonical(false);
242 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
243 representer.setPropertyUtils(new UnsortedPropertyUtils());
244 Yaml yaml = new Yaml(representer, options);
245 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
246 StringBuilder sb = new StringBuilder();
247 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
248 sb.append(yamlAsString);
249 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
250 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
253 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
254 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
255 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
256 if (fillImports.isRight()) {
257 return Either.right(fillImports.right().value());
259 return Either.left(fillImports.left().value().left);
262 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
263 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
264 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
265 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
266 return Either.right(ToscaError.GENERAL_ERROR);
268 log.trace("start tosca export for {}", component.getUniqueId());
269 String toscaVersion = null;
270 if (component instanceof Resource) {
271 toscaVersion = ((Resource) component).getToscaVersion();
273 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
274 toscaTemplate.setMetadata(convertMetadata(component));
275 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
276 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
277 if (ModelConverter.isAtomicComponent(component)) {
278 log.trace("convert component as node type");
279 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
281 log.trace("convert component as topology template");
282 return convertToscaTemplate(component, toscaTemplate);
286 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
287 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
288 if (importsRes.isRight()) {
289 return Either.right(importsRes.right().value());
291 toscaNode = importsRes.left().value().left;
292 Map<String, Component> componentCache = importsRes.left().value().right;
293 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
294 if (nodeTypesMapEither.isRight()) {
295 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
296 return Either.right(nodeTypesMapEither.right().value());
298 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
299 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
300 toscaNode.setNode_types(nodeTypesMap);
302 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
303 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
304 if (proxyInterfaceTypesEither.isRight()) {
305 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
306 return Either.right(proxyInterfaceTypesEither.right().value());
308 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
309 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
310 toscaNode.setInterface_types(proxyInterfaceTypes);
312 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
313 if (dataTypesEither.isRight()) {
314 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
315 return Either.right(ToscaError.GENERAL_ERROR);
317 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
318 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
319 List<InputDefinition> inputDef = component.getInputs();
320 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
321 if (!inputs.isEmpty()) {
322 topologyTemplate.setInputs(inputs);
324 final Map<String, ToscaProperty> outputs;
326 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
327 } catch (final ToscaConversionException e) {
328 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
329 "Could not parse component '{}' outputs. Component unique id '{}'.", new Object[]{component.getName(), component.getUniqueId(), e});
330 return Either.right(ToscaError.GENERAL_ERROR);
332 if (!outputs.isEmpty()) {
333 topologyTemplate.setOutputs(outputs);
335 final List<ComponentInstance> componentInstances = component.getComponentInstances();
336 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
337 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
338 if (CollectionUtils.isNotEmpty(componentInstances)) {
339 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = convertNodeTemplates(component, componentInstances,
340 componentInstancesProperties, componentInstanceInterfaces, componentCache, dataTypes, topologyTemplate);
341 if (nodeTemplates.isRight()) {
342 return Either.right(nodeTemplates.right().value());
344 log.debug("node templates converted");
345 topologyTemplate.setNode_templates(nodeTemplates.left().value());
347 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
348 .createFrom(topologyTemplate.getNode_templates());
349 if (!relationshipTemplatesMap.isEmpty()) {
350 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
352 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
353 convertSubstitutionMappingFilter(component, substitutionMapping);
354 addGroupsToTopologyTemplate(component, topologyTemplate);
356 addPoliciesToTopologyTemplate(component, topologyTemplate);
357 } catch (SdcResourceNotFoundException e) {
358 log.debug("Fail to add policies to topology template:", e);
359 return Either.right(ToscaError.GENERAL_ERROR);
361 String toscaResourceName;
362 switch (component.getComponentType()) {
364 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
365 .getToscaResourceName();
368 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
371 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
372 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
374 substitutionMapping.setNode_type(toscaResourceName);
375 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
376 if (capabilities.isRight()) {
377 return Either.right(capabilities.right().value());
379 substitutionMapping = capabilities.left().value();
380 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
381 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
382 if (requirements.isRight()) {
383 return Either.right(requirements.right().value());
385 substitutionMapping = requirements.left().value();
386 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
387 if (!propertyMappingMap.isEmpty()) {
388 substitutionMapping.setProperties(propertyMappingMap);
390 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
391 if (!attributesMappingMap.isEmpty()) {
392 substitutionMapping.setAttributes(attributesMappingMap);
394 topologyTemplate.setSubstitution_mappings(substitutionMapping);
395 toscaNode.setTopology_template(topologyTemplate);
396 return Either.left(toscaNode);
399 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
400 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
401 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
405 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
406 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
407 if (groups != null) {
408 topologyTemplate.addGroups(groups);
412 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
413 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
414 if (policies != null) {
415 topologyTemplate.addPolicies(policies);
419 private Map<String, String> convertMetadata(Component component) {
420 return convertMetadata(component, false, null);
423 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
424 Map<String, String> toscaMetadata = new LinkedHashMap<>();
425 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
426 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
428 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
429 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
430 List<CategoryDefinition> categories = component.getCategories();
431 CategoryDefinition categoryDefinition = categories.get(0);
432 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
434 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
435 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
436 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
437 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
438 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
439 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
440 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
441 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
442 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
443 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
444 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
445 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
446 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
448 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
451 switch (component.getComponentType()) {
453 Resource resource = (Resource) component;
454 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
455 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
456 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
458 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
460 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
461 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
462 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
463 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
466 Service service = (Service) component;
467 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
468 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
469 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
470 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
471 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
472 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
473 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
476 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
477 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
478 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
482 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
484 for (final String key : component.getCategorySpecificMetadata().keySet()) {
485 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
487 return toscaMetadata;
490 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
491 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
492 return INVARIANT_UUID;
494 return jsonPresentationField.getPresentation();
497 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
498 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
499 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
500 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
501 return Either.right(ToscaError.GENERAL_ERROR);
503 Map<String, Component> componentCache = new HashMap<>();
504 if (!ModelConverter.isAtomicComponent(component)) {
505 final List<Map<String, Map<String, String>>> additionalImports =
506 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
507 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
508 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
509 if (isNotEmpty(toscaArtifacts)) {
510 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
511 if (artifactDefinition != null) {
512 Map<String, Map<String, String>> importsListMember = new HashMap<>();
513 Map<String, String> interfaceFiles = new HashMap<>();
514 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
515 StringBuilder keyNameBuilder = new StringBuilder();
516 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
517 .append("-interface");
518 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
519 additionalImports.add(importsListMember);
522 List<ComponentInstance> componentInstances = component.getComponentInstances();
523 if (componentInstances != null && !componentInstances.isEmpty()) {
524 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
526 toscaTemplate.setDependencies(dependencies);
527 toscaTemplate.setImports(additionalImports);
529 log.debug("currently imports supported for VF and service only");
531 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
534 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
535 return ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports();
538 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
539 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
540 log.debug("createDependency componentCache {}", componentCache);
541 Component componentRI = componentCache.get(componentInstance.getComponentUid());
542 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
543 // all resource must be only once!
544 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
545 if ((resource.isRight()) && (log.isDebugEnabled())) {
546 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
547 componentInstance.getUniqueId());
550 final Component fetchedComponent = resource.left().value();
551 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
552 addDependencies(imports, dependencies, componentRI);
557 * Sets a componentCache from the given component/resource.
559 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
560 final Component fetchedComponent) {
561 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
562 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
563 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
564 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
565 .getToscaFullElement(componentInstance.getSourceModelUid());
566 if (sourceService.isRight() && (log.isDebugEnabled())) {
567 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
568 componentInstance.getUniqueId());
570 final Component fetchedSource = sourceService.left().value();
571 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
572 return fetchedSource;
574 return fetchedComponent;
578 * Retrieves all derived_from nodes and stores it in a predictable order.
580 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
581 final Component fetchedComponent) {
582 final Set<Component> componentsList = new LinkedHashSet<>();
583 if (fetchedComponent instanceof Resource) {
584 log.debug("fetchedComponent is a resource {}", fetchedComponent);
585 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
586 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
587 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
588 log.debug("Started entry.getValue() : {}", entry.getValue());
589 if (!NATIVE_ROOT.equals(entry.getValue())) {
590 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
591 if (resourcefetched != null && resourcefetched.isLeft()) {
592 componentsList.add(resourcefetched.left().value());
596 setImports(imports, dependencies, componentsList);
598 setImports(imports, dependencies, fetchedComponent);
604 * Returns all derived_from nodes found.
606 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
607 final Resource parentResource = (Resource) fetchedComponent;
608 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
609 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
610 componentsList.add(fetchedComponent);
611 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
612 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
613 .getToscaElement(componentInstance.getComponentUid());
614 if (resourcefetched != null && resourcefetched.isLeft()) {
615 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
616 if (MapUtils.isNotEmpty(derivedWithId)) {
617 derivedFromMapOfIdToName.putAll(derivedWithId);
622 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
624 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
625 return Optional.ofNullable(derivedFromMapOfIdToName);
629 * Creates a resource map and adds it to the import list.
631 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
632 final Set<Component> componentsList) {
633 componentsList.forEach(component -> setImports(imports, dependencies, component));
636 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
637 final Component component) {
638 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
639 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
640 if (artifactDefinition != null) {
641 final Map<String, String> files = new HashMap<>();
642 final String artifactName = artifactDefinition.getArtifactName();
643 files.put(IMPORTS_FILE_KEY, artifactName);
644 final StringBuilder keyNameBuilder = new StringBuilder();
645 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
646 keyNameBuilder.append("-");
647 keyNameBuilder.append(component.getName());
648 addImports(imports, keyNameBuilder, files);
649 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
650 if (!ModelConverter.isAtomicComponent(component)) {
651 final Map<String, String> interfaceFiles = new HashMap<>();
652 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
653 keyNameBuilder.append("-interface");
654 addImports(imports, keyNameBuilder, interfaceFiles);
660 * Adds the found resource to the import definition list.
662 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
663 final Map<String, String> files) {
664 final String mapKey = keyNameBuilder.toString();
665 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
666 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
667 importsListMember.put(keyNameBuilder.toString(), files);
668 imports.add(importsListMember);
672 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
673 Map<String, ToscaNodeType> nodeTypes) {
674 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
677 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
678 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
679 boolean isAssociatedComponent) {
680 log.debug("start convert node type for {}", component.getUniqueId());
681 ToscaNodeType toscaNodeType = createNodeType(component);
682 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
683 .getAllInterfaceLifecycleTypes();
684 if (lifecycleTypeEither.isRight()) {
685 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
686 return Either.right(ToscaError.GENERAL_ERROR);
688 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
689 .collect(Collectors.toList());
690 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
691 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
692 if (dataTypesEither.isRight()) {
693 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
694 return Either.right(ToscaError.GENERAL_ERROR);
696 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
697 List<InputDefinition> inputDef = component.getInputs();
698 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
699 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
700 addInputsToProperties(dataTypes, inputDef, mergedProperties);
701 final Map<String, ToscaAttribute> toscaAttributeMap;
703 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
704 } catch (final ToscaConversionException e) {
705 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
706 "Could not parse component '{}' attributes. Component unique id '{}'.",
707 new Object[]{component.getName(), component.getUniqueId(), e});
708 return Either.right(ToscaError.GENERAL_ERROR);
710 if (!toscaAttributeMap.isEmpty()) {
711 toscaNodeType.setAttributes(toscaAttributeMap);
713 if (CollectionUtils.isNotEmpty(component.getProperties())) {
714 List<PropertyDefinition> properties = component.getProperties();
715 Map<String, ToscaProperty> convertedProperties = properties.stream()
716 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
717 .toMap(PropertyDataDefinition::getName,
718 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
719 // merge component properties and inputs properties
720 mergedProperties.putAll(convertedProperties);
722 if (MapUtils.isNotEmpty(mergedProperties)) {
723 toscaNodeType.setProperties(mergedProperties);
725 /* convert private data_types */
726 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
727 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
728 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
729 for (DataTypeDefinition dataType : privateDataTypes) {
730 log.debug("Emitting private data type: component.name={} dataType.name={}",
731 component.getNormalizedName(), dataType.getName());
732 ToscaDataType toscaDataType = new ToscaDataType();
733 toscaDataType.setDerived_from(dataType.getDerivedFromName());
734 toscaDataType.setDescription(dataType.getDescription());
735 toscaDataType.setVersion(dataType.getVersion());
736 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
737 toscaDataType.setProperties(dataType.getProperties().stream()
738 .collect(Collectors.toMap(
739 PropertyDataDefinition::getName,
740 s -> propertyConvertor
741 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
744 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
746 toscaNode.setData_types(toscaDataTypeMap);
749 // Extracted to method for code reuse
750 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
753 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
754 final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
755 if (CollectionUtils.isEmpty(attributeList)) {
756 return Collections.emptyMap();
758 final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
759 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
760 for (final AttributeDefinition attributeDefinition : attributeList) {
761 toscaAttributeMap.put(attributeDefinition.getName(), attributeConverter.convert(attributeDefinition));
763 return toscaAttributeMap;
766 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
767 Component component, ToscaTemplate toscaNode,
768 Map<String, ToscaNodeType> nodeTypes,
769 ToscaNodeType toscaNodeType,
770 Map<String, DataTypeDefinition> dataTypes) {
771 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
773 if (capabilities.isRight()) {
774 return Either.right(capabilities.right().value());
776 toscaNodeType = capabilities.left().value();
777 log.debug("Capabilities converted for {}", component.getUniqueId());
779 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
780 .convertRequirements(componentsCache, component,
782 if (requirements.isRight()) {
783 return Either.right(requirements.right().value());
785 toscaNodeType = requirements.left().value();
786 log.debug("Requirements converted for {}", component.getUniqueId());
788 String toscaResourceName;
789 switch (component.getComponentType()) {
791 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
792 .getMetadataDataDefinition()).getToscaResourceName();
795 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
796 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
799 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
800 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
803 nodeTypes.put(toscaResourceName, toscaNodeType);
804 toscaNode.setNode_types(nodeTypes);
805 log.debug("finish convert node type for {}", component.getUniqueId());
806 return Either.left(toscaNode);
809 protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(
811 List<ComponentInstance> componentInstances,
812 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
813 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
814 Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes,
815 ToscaTopolgyTemplate topologyTemplate) {
817 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
818 log.debug("start convert topology template for {} for type {}", component.getUniqueId(),
819 component.getComponentType());
820 Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
821 Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
823 Map<String, ToscaGroupTemplate> groupsMap = null;
824 for (ComponentInstance componentInstance : componentInstances) {
825 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
826 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
827 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
829 nodeTemplate.setType(componentInstance.getToscaComponentName());
830 nodeTemplate.setDirectives(componentInstance.getDirectives());
831 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
833 Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
834 .getOriginComponent(componentCache, componentInstance);
835 if (originComponentRes.isRight()) {
836 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
839 Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component,
840 componentInstance, component.getComponentInstancesRelations(), nodeTemplate,
841 originComponentRes.left().value(), componentCache);
842 if (requirements.isRight()) {
843 convertNodeTemplatesRes = Either.right(requirements.right().value());
846 String instanceUniqueId = componentInstance.getUniqueId();
847 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
849 nodeTemplate = requirements.left().value();
851 Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
853 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
854 Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
855 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
857 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
860 Either<ToscaNodeTemplate, ToscaError> capabilities = capabilityRequirementConverter
861 .convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
862 if (capabilities.isRight()) {
863 convertNodeTemplatesRes = Either.right(capabilities.right().value());
866 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
868 nodeTemplate = capabilities.left().value();
869 Map<String, Object> props = new HashMap<>();
871 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
872 // Adds the properties of parent component to map
873 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
876 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
877 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId,
881 if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)
882 && !isComponentOfTypeServiceProxy(componentInstance)) {
883 //For service proxy the inputs are already handled under instance properties above
884 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
887 //M3[00001] - NODE TEMPLATE INTERFACES - START
888 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate,
889 instanceUniqueId, component);
890 //M3[00001] - NODE TEMPLATE INTERFACES - END
891 if (props != null && !props.isEmpty()) {
892 nodeTemplate.setProperties(props);
895 List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
896 if (groupInstances != null) {
897 if (groupsMap == null) {
898 groupsMap = new HashMap<>();
900 for (GroupInstance groupInst : groupInstances) {
901 boolean addToTosca = true;
903 List<String> artifacts = groupInst.getArtifacts();
904 if (artifacts == null || artifacts.isEmpty()) {
909 ToscaGroupTemplate toscaGroup = groupExportParser
910 .getToscaGroupTemplate(groupInst, componentInstance.getInvariantName());
911 groupsMap.put(groupInst.getName(), toscaGroup);
916 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
918 if (groupsMap != null) {
919 log.debug("instance groups added");
920 topologyTemplate.addGroups(groupsMap);
922 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
923 ((Service) component).getForwardingPaths())) {
924 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(),
925 component.getName());
926 ForwardingPathToscaUtil
927 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache,
928 toscaOperationFacade);
929 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(),
930 component.getName());
932 if (convertNodeTemplatesRes == null) {
933 convertNodeTemplatesRes = Either.left(nodeTemplates);
935 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(),
936 component.getComponentType());
937 return convertNodeTemplatesRes;
940 private void handleInstanceInterfaces(
941 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
942 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
943 String instanceUniqueId,
944 Component parentComponent) {
946 if (MapUtils.isEmpty(componentInstanceInterfaces)
947 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
948 nodeTemplate.setInterfaces(null);
952 final List<ComponentInstanceInterface> currServiceInterfaces =
953 componentInstanceInterfaces.get(instanceUniqueId);
955 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
956 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
957 .getUniqueId(), instInterface));
959 final Map<String, Object> interfaceMap = interfacesOperationsConverter
960 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
961 isComponentOfTypeServiceProxy(componentInstance));
963 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
964 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
967 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
968 return Objects.nonNull(componentInstance.getOriginType())
969 && componentInstance.getOriginType().getValue().equals("Service Proxy");
972 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
973 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
974 String instanceUniqueId, Map<String, Object> props) {
976 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
977 if (instanceInputsList != null) {
978 instanceInputsList.forEach(input -> {
980 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
981 ? input.getValue() : input.getDefaultValue();
982 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
987 private void addPropertiesOfComponentInstance(
988 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
989 Map<String, DataTypeDefinition> dataTypes, String instanceUniqueId,
990 Map<String, Object> props) {
992 if (isNotEmpty(componentInstancesProperties)) {
993 componentInstancesProperties.get(instanceUniqueId)
994 // Converts and adds each value to property map
995 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
1000 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1001 Component componentOfInstance, Map<String, Object> props) {
1003 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1004 if (isNotEmpty(componentProperties)) {
1005 componentProperties.stream()
1006 // Filters out properties with empty default values
1007 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1008 // Converts and adds each value to property map
1009 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
1010 prop::getDefaultValue));
1014 private ToscaNodeType createNodeType(Component component) {
1015 ToscaNodeType toscaNodeType = new ToscaNodeType();
1016 if (ModelConverter.isAtomicComponent(component)) {
1017 if (((Resource) component).getDerivedFrom() != null) {
1018 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1020 toscaNodeType.setDescription(component.getDescription());
1022 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1024 toscaNodeType.setDerived_from(derivedFrom);
1026 return toscaNodeType;
1029 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1031 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1032 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1033 List<ComponentInstance> componentInstances = container.getComponentInstances();
1034 if (CollectionUtils.isEmpty(componentInstances)) {
1037 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1038 componentInstances.stream()
1039 .filter(this::isComponentOfTypeServiceProxy)
1040 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1041 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1044 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1045 Component serviceComponent;
1046 ComponentParametersView componentParametersView = new ComponentParametersView();
1047 componentParametersView.disableAll();
1048 componentParametersView.setIgnoreInterfaces(false);
1049 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1050 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1051 if (service.isRight()) {
1052 log.debug("Failed to fetch original service component with id {} for instance {}",
1053 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1054 return Either.right(ToscaError.GENERAL_ERROR);
1056 serviceComponent = service.left().value();
1059 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1060 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
1061 if (lifecycleTypeEither.isRight()) {
1062 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1063 return Either.right(ToscaError.GENERAL_ERROR);
1066 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1067 .map(InterfaceDataDefinition::getType)
1068 .collect(Collectors.toList());
1069 //Add interface types for local interfaces in the original service component for proxy
1070 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1071 allGlobalInterfaceTypes);
1072 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1073 proxyInterfaceTypes.putAll(localInterfaceTypes);
1077 return Either.left(proxyInterfaceTypes);
1080 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1081 Component container) {
1083 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1084 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1086 List<ComponentInstance> componentInstances = container.getComponentInstances();
1088 if (componentInstances == null || componentInstances.isEmpty()) {
1091 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1092 List<ComponentInstance> proxyInst = componentInstances.stream()
1093 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1094 .collect(Collectors.toList());
1095 if (proxyInst != null && !proxyInst.isEmpty()) {
1096 for (ComponentInstance inst : proxyInst) {
1097 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1101 if (serviceProxyInstanceList.isEmpty()) {
1104 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1105 .getLatestByName("serviceProxy");
1106 if (serviceProxyOrigin.isRight()) {
1107 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1108 serviceProxyOrigin.right().value());
1109 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1111 Component origComponent = serviceProxyOrigin.left().value();
1113 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1114 Component serviceComponent = null;
1115 ComponentParametersView componentParametersView = new ComponentParametersView();
1116 componentParametersView.disableAll();
1117 componentParametersView.setIgnoreCategories(false);
1118 componentParametersView.setIgnoreProperties(false);
1119 componentParametersView.setIgnoreInputs(false);
1120 componentParametersView.setIgnoreInterfaces(false);
1121 componentParametersView.setIgnoreRequirements(false);
1122 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1123 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1124 if (service.isRight()) {
1125 log.debug("Failed to fetch resource with id {} for instance {}",
1126 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1128 serviceComponent = service.left().value();
1131 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1132 entryProxy.getValue());
1133 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1136 return Either.left(nodeTypesMap);
1139 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1140 final Component container, final ToscaTemplate toscaNode) {
1141 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1143 if (CollectionUtils.isEmpty(componentInstances)) {
1146 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1147 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1148 .collect(Collectors.toList());
1149 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1150 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1151 final Map<String, ToscaNodeType> nodeTypes =
1152 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1153 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1159 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1160 Component proxyComponent, ComponentInstance componentInstance) {
1161 ToscaNodeType toscaNodeType = new ToscaNodeType();
1162 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1164 toscaNodeType.setDerived_from(derivedFrom);
1165 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1166 if (dataTypesEither.isRight()) {
1167 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1169 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1170 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1171 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1173 if (MapUtils.isNotEmpty(capabilities)) {
1174 toscaNodeType.setCapabilities(capabilities);
1176 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1177 .convertProxyRequirements(componentCache, componentInstance);
1178 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1179 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1181 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1182 proxyProperties.ifPresent(toscaNodeType::setProperties);
1184 Map<String, Object> interfaceMap = new HashMap<>();
1185 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1186 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1187 if (proxyInterfaces.isPresent()) {
1188 interfaceMap = proxyInterfaces.get();
1191 interfaceMap = interfacesOperationsConverter
1192 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1195 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1196 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1198 return toscaNodeType;
1201 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1202 ComponentInstance componentInstance,
1203 List<RequirementCapabilityRelDef> relations,
1204 ToscaNodeTemplate nodeTypeTemplate,
1205 Component originComponent,
1206 Map<String, Component> componentCache) {
1208 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements;
1209 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1211 if (isNotEmpty(requirementDefinitionList)) {
1213 toscaRequirements = buildRequirements(component, componentInstance,
1214 requirementDefinitionList, originComponent, componentCache);
1215 if (!toscaRequirements.isEmpty()) {
1216 nodeTypeTemplate.setRequirements(toscaRequirements);
1218 } catch (final Exception e) {
1219 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1220 componentInstance.getName(), e);
1221 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1224 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1225 return Either.left(nodeTypeTemplate);
1228 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1229 final ComponentInstance componentInstance,
1230 final List<RequirementCapabilityRelDef> filteredRelations,
1231 final Component originComponent,
1232 final Map<String, Component> componentCache)
1233 throws ToscaExportException {
1235 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1236 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1237 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1238 buildRequirement(componentInstance, originComponent, component.getComponentInstances(),
1239 relationshipDefinition, componentCache);
1240 toscaRequirements.add(toscaTemplateRequirementMap);
1243 return toscaRequirements;
1246 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1247 List<RequirementCapabilityRelDef> relations) {
1248 return relations.stream()
1249 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1252 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1253 final Component fromOriginComponent,
1254 final List<ComponentInstance> instancesList,
1255 final RequirementCapabilityRelDef relationshipDefinition,
1256 final Map<String, Component> componentCache)
1257 throws ToscaExportException {
1259 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1260 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1261 .getRelationships().get(0);
1262 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1264 final ComponentInstance toInstance = instancesList.stream()
1265 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1266 .findFirst().orElse(null);
1267 if (toInstance == null) {
1268 final String errorMsg = String
1269 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1270 relationshipDefinition.getToNode());
1271 log.debug(errorMsg);
1272 throw new ToscaExportException(errorMsg);
1274 final Optional<RequirementDefinition> reqOpt =
1275 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1276 if (reqOpt.isEmpty()) {
1277 final String errorMsg = String
1278 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1279 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1280 log.debug(errorMsg);
1281 throw new ToscaExportException(errorMsg);
1283 final ComponentParametersView filter = new ComponentParametersView(true);
1284 filter.setIgnoreComponentInstances(false);
1285 filter.setIgnoreCapabilities(false);
1286 filter.setIgnoreGroups(false);
1287 final Either<Component, StorageOperationStatus> getOriginRes =
1288 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1289 if (getOriginRes.isRight()) {
1290 final String errorMsg = String.format(
1291 "Failed to build substituted name for the requirement %s. "
1292 + "Failed to get an origin component with uniqueId %s",
1293 reqOpt.get().getName(), toInstance.getActualComponentUid());
1294 log.debug(errorMsg);
1295 throw new ToscaExportException(errorMsg);
1297 final Component toOriginComponent = getOriginRes.left().value();
1298 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1299 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1300 if (capOpt.isEmpty()) {
1301 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1302 if (capOpt.isEmpty()) {
1303 final String errorMsg = String
1304 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1305 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1306 log.debug(errorMsg);
1307 throw new ToscaExportException(errorMsg);
1310 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1311 capabilityRequirementRelationship, toInstance, componentCache);
1314 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1315 CapabilityDefinition capability) {
1316 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1317 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1320 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1321 Component toOriginComponent, Component fromOriginComponent,
1322 RequirementDefinition requirement) {
1323 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1324 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1325 if (!cap.isPresent()) {
1326 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1327 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1332 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1333 final Component toOriginComponent,
1334 final CapabilityDefinition capability,
1335 final RequirementDefinition requirement,
1336 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1337 final ComponentInstance toInstance,
1338 final Map<String, Component> componentCache)
1339 throws ToscaExportException {
1341 List<String> reducedPath = capability.getPath();
1342 if (capability.getOwnerId() != null) {
1343 reducedPath = capabilityRequirementConverter
1344 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1346 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1347 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1348 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1349 if (capabilityNameEither.isRight()) {
1350 final String errorMsg = String.format(
1351 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1352 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1355 throw new ToscaExportException(errorMsg);
1357 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1358 .buildSubstitutedName(componentCache, fromOriginComponent,
1359 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1360 if (requirementNameEither.isRight()) {
1361 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1362 + "with name %s on a component with uniqueId %s",
1363 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1364 log.debug(errorMsg);
1365 throw new ToscaExportException(errorMsg);
1367 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1368 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1369 toscaRequirement.setNode(toInstance.getName());
1370 toscaRequirement.setCapability(capabilityNameEither.left().value());
1371 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1372 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1374 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1378 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1379 Map<String, List<RequirementDefinition>> reqMap,
1380 RelationshipInfo reqAndRelationshipPair,
1381 String fromInstanceId) {
1382 for (List<RequirementDefinition> reqList : reqMap.values()) {
1383 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1384 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1386 if (reqOpt.isPresent()) {
1390 return Optional.empty();
1394 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1395 * 1.The name of the requirement equals to the "requirement" field of the relation; AND 2. In case of a non-atomic resource, OwnerId of the
1396 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1398 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1399 RequirementDefinition requirement, String fromInstanceId) {
1400 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1401 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1402 reqAndRelationshipPair.getRequirement());
1405 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1409 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1410 Component originComponent) {
1411 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1412 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1413 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1416 private boolean isCvfc(Component component) {
1417 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1420 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1421 Map<String, Component> componentCache) {
1422 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1423 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1424 .convertSubstitutionMappingCapabilities(componentCache, component);
1425 if (toscaCapabilitiesRes.isRight()) {
1426 result = Either.right(toscaCapabilitiesRes.right().value());
1427 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1428 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1429 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1430 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1432 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1436 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1437 Map<String, DataTypeDefinition> dataTypes) {
1438 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1439 if (!toscaCapabilities.isEmpty()) {
1440 nodeType.setCapabilities(toscaCapabilities);
1442 log.debug("Finish convert Capabilities for node type");
1443 return Either.left(nodeType);
1446 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1447 if (artifacts == null) {
1450 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1451 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1452 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1453 artifact.setFile(entry.getValue().getFile());
1454 artifact.setType(entry.getValue().getType());
1455 arts.put(entry.getKey(), artifact);
1460 protected NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1461 if (inNodeFilter == null) {
1464 NodeFilter nodeFilter = new NodeFilter();
1465 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1466 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1467 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1468 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1469 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1470 copyNodeFilterProperties(origProperties, propertiesCopy);
1471 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1472 nodeFilter.setCapabilities(capabilitiesCopy);
1474 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1475 nodeFilter.setProperties(propertiesCopy);
1477 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1478 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1482 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1483 if (substitutionFilterDataDefinition == null) {
1486 NodeFilter nodeFilter = new NodeFilter();
1487 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1488 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1489 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1490 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1491 nodeFilter.setProperties(propertiesCopy);
1493 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1494 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1497 private Object cloneToscaId(Object toscaId) {
1498 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1501 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1502 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1503 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1506 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1507 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1508 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1512 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1513 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1514 CapabilityFilter capabilityFilter = new CapabilityFilter();
1515 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1516 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1517 capabilityFilter.setProperties(propertiesCopy);
1518 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1519 capabilitiesCopy.add(capabilityFilterCopyMap);
1523 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1524 List<Map<String, List<Object>>> propertiesCopy) {
1525 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1528 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1529 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1530 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1531 Map propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1532 String propertyName = propertyDataDefinition.getName();
1533 if (propertyMapCopy.containsKey(propertyName)) {
1534 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1536 if (propertyName != null) {
1537 List<Object> propsList = new ArrayList<>();
1538 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1539 propertyMapCopy.put(propertyName, propsList);
1541 propertyMapCopy.putAll(propertyValObj);
1546 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1549 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1550 final List<Map<String, List<Object>>> propertiesCopy) {
1551 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1554 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1555 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1556 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1557 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1558 final String propertyName = propertyDataDefinition.getName();
1559 if (propertyMapCopy.containsKey(propertyName)) {
1560 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1562 if (propertyName != null) {
1563 final List<Object> propsList = new ArrayList<>();
1564 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1565 propertyMapCopy.put(propertyName, propsList);
1567 propertyMapCopy.putAll(propertyValObj);
1572 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1575 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1576 if (propertyValObj.containsKey(propertyName)) {
1577 propsList.add(propertyValObj.get(propertyName));
1579 propsList.add(propertyValObj);
1583 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1584 Map<String, List<Object>> tempMap = new HashMap<>();
1585 tempMap.put(entry.getKey(), entry.getValue());
1586 propertiesCopy.add(tempMap);
1589 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1590 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1591 return Collections.emptyMap();
1593 return component.getInputs().stream().filter(input -> input.isMappedToComponentProperty()).map(PropertyDataDefinition::getName)
1594 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1597 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1598 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1599 return Collections.emptyMap();
1601 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1602 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1605 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1606 if (Objects.isNull(proxyComponent)) {
1607 return Optional.empty();
1609 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1610 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1611 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1612 proxyProperties.putAll(proxyComponent.getProperties().stream()
1613 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1614 .toMap(PropertyDataDefinition::getName,
1615 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1617 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1620 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1621 Map<String, ToscaProperty> mergedProperties) {
1622 if (CollectionUtils.isEmpty(componentInputs)) {
1625 for (InputDefinition input : componentInputs) {
1626 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1627 mergedProperties.put(input.getName(), property);
1631 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1632 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1633 return Optional.empty();
1635 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1636 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1638 // always available in the proxy node template
1639 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1641 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1644 private static class CustomRepresenter extends Representer {
1646 CustomRepresenter() {
1648 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1649 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1650 // null representer is exceptional and it is stored as an instance
1653 this.nullRepresenter = new RepresentNull();
1656 public boolean validateGetInputValue(final Object valueObj) {
1657 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1660 if (valueObj instanceof List) {
1661 return ((List) valueObj).size() > 1;
1666 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1667 if (valueObj instanceof List) {
1668 return ((List) valueObj).size() > 1;
1674 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1675 if (propertyValue == null) {
1678 // skip not relevant for Tosca property
1679 if ("dependencies".equals(property.getName())) {
1682 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1685 removeDefaultP(propertyValue);
1686 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1687 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1688 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1690 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1693 private void removeDefaultP(final Object propertyValue) {
1694 if (propertyValue instanceof Map) {
1695 final Map mapPropertyValue = ((Map) propertyValue);
1696 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1697 Object defaultValue = null;
1698 while (iter.hasNext()) {
1699 final Map.Entry entry = iter.next();
1700 if ("_defaultp_".equals(entry.getKey())) {
1701 defaultValue = entry.getValue();
1703 } else if (entry.getValue() instanceof Map) {
1704 removeDefaultP(entry.getValue());
1707 if (defaultValue != null) {
1708 mapPropertyValue.putIfAbsent("default", defaultValue);
1714 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1715 // remove the bean type from the output yaml (!! ...)
1716 if (!classTags.containsKey(javaBean.getClass())) {
1717 addClassTag(javaBean.getClass(), Tag.MAP);
1719 return super.representJavaBean(properties, javaBean);
1722 private class RepresentToscaAttribute implements Represent {
1725 public Node representData(Object data) {
1726 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1727 return represent(toscaAttribute.asToscaMap());
1731 private class RepresentToscaPropertyAssignment implements Represent {
1733 public Node representData(Object data) {
1734 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1735 if (toscaOperationAssignment.getValue() instanceof String) {
1736 final String stringValue = (String) toscaOperationAssignment.getValue();
1737 if (isPropertyOrAttributeFunction(stringValue)) {
1738 return representGetAttribute(stringValue);
1740 return representScalar(Tag.STR, stringValue);
1742 return represent(null);
1745 public Node representGetAttribute(final String getAttributeFunction) {
1746 return represent(new Yaml().load(getAttributeFunction));
1749 public boolean isPropertyOrAttributeFunction(final String value) {
1751 final Yaml yaml = new Yaml();
1752 final Object yamlObj = yaml.load(value);
1753 if (!(yamlObj instanceof Map)) {
1756 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1757 if (getAttributeMap.size() != 1) {
1760 final List<String> functionList = Arrays
1761 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1762 final Optional<String> function = getAttributeMap.keySet().stream()
1763 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1764 if (function.isEmpty()) {
1767 final String functionName = function.get();
1768 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1769 if (GET_INPUT.getFunctionName().equals(functionName)) {
1770 return validateGetInputValue(getAttributeValueObj);
1772 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1774 } catch (final Exception ignored) {
1780 private class RepresentNull implements Represent {
1783 public Node representData(Object data) {
1784 // possible values are here http://yaml.org/type/null.html
1785 return representScalar(Tag.NULL, "");
1790 private static class UnsortedPropertyUtils extends PropertyUtils {
1793 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1794 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1795 return new LinkedHashSet<>(fields);