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.nio.file.Path;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.LinkedHashMap;
40 import java.util.LinkedHashSet;
41 import java.util.List;
43 import java.util.Map.Entry;
44 import java.util.Objects;
45 import java.util.Optional;
47 import java.util.function.Supplier;
48 import java.util.stream.Collectors;
49 import org.apache.commons.collections.CollectionUtils;
50 import org.apache.commons.collections.MapUtils;
51 import org.apache.commons.io.FilenameUtils;
52 import org.apache.commons.lang3.StringUtils;
53 import org.apache.commons.lang3.tuple.ImmutablePair;
54 import org.apache.commons.lang3.tuple.ImmutableTriple;
55 import org.apache.commons.lang3.tuple.Triple;
56 import org.onap.sdc.tosca.services.YamlUtil;
57 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
58 import org.openecomp.sdc.be.config.Configuration;
59 import org.openecomp.sdc.be.config.ConfigurationManager;
60 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
61 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
62 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
70 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
71 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
73 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
74 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
75 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
76 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
77 import org.openecomp.sdc.be.exception.ToscaExportException;
78 import org.openecomp.sdc.be.model.ArtifactDefinition;
79 import org.openecomp.sdc.be.model.AttributeDefinition;
80 import org.openecomp.sdc.be.model.CapabilityDefinition;
81 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
82 import org.openecomp.sdc.be.model.Component;
83 import org.openecomp.sdc.be.model.ComponentInstance;
84 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
85 import org.openecomp.sdc.be.model.ComponentInstanceInput;
86 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
87 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
88 import org.openecomp.sdc.be.model.ComponentParametersView;
89 import org.openecomp.sdc.be.model.DataTypeDefinition;
90 import org.openecomp.sdc.be.model.GroupInstance;
91 import org.openecomp.sdc.be.model.InputDefinition;
92 import org.openecomp.sdc.be.model.InterfaceDefinition;
93 import org.openecomp.sdc.be.model.PropertyDefinition;
94 import org.openecomp.sdc.be.model.RelationshipInfo;
95 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
96 import org.openecomp.sdc.be.model.RequirementDefinition;
97 import org.openecomp.sdc.be.model.Resource;
98 import org.openecomp.sdc.be.model.Service;
99 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
100 import org.openecomp.sdc.be.model.category.CategoryDefinition;
101 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
102 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
103 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
104 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
105 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
106 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
107 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
108 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
109 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
110 import org.openecomp.sdc.be.tosca.model.NodeFilter;
111 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
112 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
113 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
114 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
115 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
116 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
117 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
118 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
119 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
120 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
121 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
122 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
123 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
124 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
125 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
126 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
127 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
128 import org.openecomp.sdc.be.tosca.utils.InputConverter;
129 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
130 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
131 import org.openecomp.sdc.common.log.wrappers.Logger;
132 import org.springframework.beans.factory.annotation.Autowired;
133 import org.yaml.snakeyaml.DumperOptions;
134 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
135 import org.yaml.snakeyaml.Yaml;
136 import org.yaml.snakeyaml.introspector.BeanAccess;
137 import org.yaml.snakeyaml.introspector.Property;
138 import org.yaml.snakeyaml.introspector.PropertyUtils;
139 import org.yaml.snakeyaml.nodes.MappingNode;
140 import org.yaml.snakeyaml.nodes.Node;
141 import org.yaml.snakeyaml.nodes.NodeTuple;
142 import org.yaml.snakeyaml.nodes.Tag;
143 import org.yaml.snakeyaml.representer.Represent;
144 import org.yaml.snakeyaml.representer.Representer;
146 @org.springframework.stereotype.Component("tosca-export-handler")
147 public class ToscaExportHandler {
149 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
150 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
151 private static final String INVARIANT_UUID = "invariantUUID";
152 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
153 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
154 private static final String IMPORTS_FILE_KEY = "file";
155 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
156 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
157 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
158 private static final String NATIVE_ROOT = "tosca.nodes.Root";
159 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
160 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
161 private static final YamlUtil yamlUtil = new YamlUtil();
162 private final ApplicationDataTypeCache applicationDataTypeCache;
163 private final ToscaOperationFacade toscaOperationFacade;
164 private final CapabilityRequirementConverter capabilityRequirementConverter;
165 private final PolicyExportParser policyExportParser;
166 private final GroupExportParser groupExportParser;
167 private final PropertyConvertor propertyConvertor;
168 private final AttributeConverter attributeConverter;
169 private final InputConverter inputConverter;
170 private final OutputConverter outputConverter;
171 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
172 private final InterfacesOperationsConverter interfacesOperationsConverter;
173 private final ModelOperation modelOperation;
176 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
177 final ToscaOperationFacade toscaOperationFacade,
178 final CapabilityRequirementConverter capabilityRequirementConverter,
179 final PolicyExportParser policyExportParser,
180 final GroupExportParser groupExportParser,
181 final PropertyConvertor propertyConvertor,
182 final AttributeConverter attributeConverter,
183 final InputConverter inputConverter,
184 final OutputConverter outputConverter,
185 final InterfaceLifecycleOperation interfaceLifecycleOperation,
186 final InterfacesOperationsConverter interfacesOperationsConverter,
187 final ModelOperation modelOperation) {
188 this.applicationDataTypeCache = applicationDataTypeCache;
189 this.toscaOperationFacade = toscaOperationFacade;
190 this.capabilityRequirementConverter = capabilityRequirementConverter;
191 this.policyExportParser = policyExportParser;
192 this.groupExportParser = groupExportParser;
193 this.propertyConvertor = propertyConvertor;
194 this.attributeConverter = attributeConverter;
195 this.inputConverter = inputConverter;
196 this.outputConverter = outputConverter;
197 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
198 this.interfacesOperationsConverter = interfacesOperationsConverter;
199 this.modelOperation = modelOperation;
202 public static String getInterfaceFilename(String artifactName) {
203 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
206 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
207 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
210 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
211 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
214 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
215 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
218 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
219 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
220 if (CollectionUtils.isEmpty(imports)) {
221 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
222 return Either.right(ToscaError.GENERAL_ERROR);
224 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
225 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
226 .startsWith("org.openecomp.resource.abstract.nodes.")) {
227 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
228 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(), component.getModel());
229 if (baseType.isLeft() && baseType.left().value() != null) {
230 addDependencies(imports, dependencies, baseType.left().value());
232 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
236 String toscaVersion = null;
237 if (component instanceof Resource) {
238 toscaVersion = ((Resource) component).getToscaVersion();
240 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
241 toscaTemplate.setImports(imports);
242 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
243 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
244 isAssociatedComponent);
245 if (toscaTemplateRes.isRight()) {
246 return Either.right(toscaTemplateRes.right().value());
248 toscaTemplate = toscaTemplateRes.left().value();
249 toscaTemplate.setDependencies(dependencies);
250 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
251 return Either.left(toscaRepresentation);
254 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
255 CustomRepresenter representer = new CustomRepresenter();
256 DumperOptions options = new DumperOptions();
257 options.setAllowReadOnlyProperties(false);
258 options.setPrettyFlow(true);
259 options.setDefaultFlowStyle(FlowStyle.FLOW);
260 options.setCanonical(false);
261 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
262 representer.setPropertyUtils(new UnsortedPropertyUtils());
263 Yaml yaml = new Yaml(representer, options);
264 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
265 StringBuilder sb = new StringBuilder();
266 sb.append(getConfiguration().getHeatEnvArtifactHeader());
267 sb.append(yamlAsString);
268 sb.append(getConfiguration().getHeatEnvArtifactFooter());
269 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
272 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
273 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
274 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
275 if (fillImports.isRight()) {
276 return Either.right(fillImports.right().value());
278 return Either.left(fillImports.left().value().left);
281 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
282 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
283 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
284 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
285 return Either.right(ToscaError.GENERAL_ERROR);
287 log.trace("start tosca export for {}", component.getUniqueId());
288 String toscaVersion = null;
289 if (component instanceof Resource) {
290 toscaVersion = ((Resource) component).getToscaVersion();
292 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
293 toscaTemplate.setMetadata(convertMetadata(component));
294 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
295 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
296 if (ModelConverter.isAtomicComponent(component)) {
297 log.trace("convert component as node type");
298 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
300 log.trace("convert component as topology template");
301 return convertToscaTemplate(component, toscaTemplate);
305 public List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
306 if (modelId == null) {
307 return getDefaultToscaImportConfig();
310 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
311 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
312 final Set<Path> addedPathList = new HashSet<>();
313 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
314 var importPath = Path.of(toscaImportByModel.getFullPath());
315 if (addedPathList.contains(importPath)) {
316 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
318 final String fileName = FilenameUtils.getBaseName(importPath.toString());
319 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
320 addedPathList.add(importPath);
325 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
326 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
327 if (importsRes.isRight()) {
328 return Either.right(importsRes.right().value());
330 toscaNode = importsRes.left().value().left;
331 Map<String, Component> componentCache = importsRes.left().value().right;
332 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
333 if (nodeTypesMapEither.isRight()) {
334 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
335 return Either.right(nodeTypesMapEither.right().value());
337 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
338 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
339 toscaNode.setNode_types(nodeTypesMap);
341 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
342 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
343 if (proxyInterfaceTypesEither.isRight()) {
344 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
345 return Either.right(proxyInterfaceTypesEither.right().value());
347 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
348 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
349 toscaNode.setInterface_types(proxyInterfaceTypes);
351 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
352 if (dataTypesEither.isRight()) {
353 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
354 return Either.right(ToscaError.GENERAL_ERROR);
356 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
357 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
358 List<InputDefinition> inputDef = component.getInputs();
359 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
360 if (!inputs.isEmpty()) {
361 topologyTemplate.setInputs(inputs);
363 final Map<String, ToscaProperty> outputs;
365 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
366 } catch (final ToscaConversionException e) {
367 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
368 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
369 return Either.right(ToscaError.GENERAL_ERROR);
371 if (!outputs.isEmpty()) {
372 topologyTemplate.setOutputs(outputs);
374 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
375 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
376 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
377 if (nodeTemplates.isRight()) {
378 return Either.right(nodeTemplates.right().value());
380 log.debug("node templates converted");
381 topologyTemplate.setNode_templates(nodeTemplates.left().value());
383 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
384 .createFrom(topologyTemplate.getNode_templates());
385 if (!relationshipTemplatesMap.isEmpty()) {
386 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
388 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
389 convertSubstitutionMappingFilter(component, substitutionMapping);
390 addGroupsToTopologyTemplate(component, topologyTemplate);
392 addPoliciesToTopologyTemplate(component, topologyTemplate);
393 } catch (SdcResourceNotFoundException e) {
394 log.debug("Fail to add policies to topology template:", e);
395 return Either.right(ToscaError.GENERAL_ERROR);
397 String toscaResourceName;
398 switch (component.getComponentType()) {
400 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
401 .getToscaResourceName();
404 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
407 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
408 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
410 substitutionMapping.setNode_type(toscaResourceName);
411 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
412 if (capabilities.isRight()) {
413 return Either.right(capabilities.right().value());
415 substitutionMapping = capabilities.left().value();
416 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
417 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
418 if (requirements.isRight()) {
419 return Either.right(requirements.right().value());
421 substitutionMapping = requirements.left().value();
422 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
423 if (!propertyMappingMap.isEmpty()) {
424 substitutionMapping.setProperties(propertyMappingMap);
426 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
427 if (!attributesMappingMap.isEmpty()) {
428 substitutionMapping.setAttributes(attributesMappingMap);
430 topologyTemplate.setSubstitution_mappings(substitutionMapping);
431 toscaNode.setTopology_template(topologyTemplate);
432 return Either.left(toscaNode);
435 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
436 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
437 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
441 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
442 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
443 if (groups != null) {
444 topologyTemplate.addGroups(groups);
448 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
449 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
450 if (policies != null) {
451 topologyTemplate.addPolicies(policies);
455 private Map<String, String> convertMetadata(Component component) {
456 return convertMetadata(component, false, null);
459 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
460 Map<String, String> toscaMetadata = new LinkedHashMap<>();
461 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
462 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
464 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
465 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
466 List<CategoryDefinition> categories = component.getCategories();
467 CategoryDefinition categoryDefinition = categories.get(0);
468 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
470 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
471 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
472 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
473 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
474 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
475 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
476 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
477 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
478 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
479 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
480 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
481 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
482 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
484 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
487 switch (component.getComponentType()) {
489 Resource resource = (Resource) component;
490 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
491 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
492 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
494 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
496 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
497 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
498 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
499 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
502 Service service = (Service) component;
503 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
504 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
505 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
506 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
507 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
508 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
509 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
512 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
513 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
514 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
518 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
520 for (final String key : component.getCategorySpecificMetadata().keySet()) {
521 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
522 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
525 return toscaMetadata;
528 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
529 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
530 return INVARIANT_UUID;
532 return jsonPresentationField.getPresentation();
535 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
536 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
537 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
538 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
539 return Either.right(ToscaError.GENERAL_ERROR);
541 Map<String, Component> componentCache = new HashMap<>();
542 if (!ModelConverter.isAtomicComponent(component)) {
543 final List<Map<String, Map<String, String>>> additionalImports =
544 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
545 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
546 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
547 if (isNotEmpty(toscaArtifacts)) {
548 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
549 if (artifactDefinition != null) {
550 Map<String, Map<String, String>> importsListMember = new HashMap<>();
551 Map<String, String> interfaceFiles = new HashMap<>();
552 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
553 StringBuilder keyNameBuilder = new StringBuilder();
554 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
555 .append("-interface");
556 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
557 additionalImports.add(importsListMember);
560 List<ComponentInstance> componentInstances = component.getComponentInstances();
561 if (componentInstances != null && !componentInstances.isEmpty()) {
562 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
564 toscaTemplate.setDependencies(dependencies);
565 toscaTemplate.setImports(additionalImports);
567 log.debug("currently imports supported for VF and service only");
569 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
572 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
573 return getConfiguration().getDefaultImports();
576 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
577 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
578 log.debug("createDependency componentCache {}", componentCache);
579 Component componentRI = componentCache.get(componentInstance.getComponentUid());
580 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
581 // all resource must be only once!
582 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
583 if ((resource.isRight()) && (log.isDebugEnabled())) {
584 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
585 componentInstance.getUniqueId());
588 final Component fetchedComponent = resource.left().value();
589 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
590 addDependencies(imports, dependencies, componentRI);
595 * Sets a componentCache from the given component/resource.
597 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
598 final Component fetchedComponent) {
599 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
600 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
601 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
602 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
603 .getToscaFullElement(componentInstance.getSourceModelUid());
604 if (sourceService.isRight() && (log.isDebugEnabled())) {
605 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
606 componentInstance.getUniqueId());
608 final Component fetchedSource = sourceService.left().value();
609 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
610 return fetchedSource;
612 return fetchedComponent;
616 * Retrieves all derived_from nodes and stores it in a predictable order.
618 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
619 final Component fetchedComponent) {
620 final Set<Component> componentsList = new LinkedHashSet<>();
621 if (fetchedComponent instanceof Resource) {
622 log.debug("fetchedComponent is a resource {}", fetchedComponent);
623 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
624 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
625 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
626 log.debug("Started entry.getValue() : {}", entry.getValue());
627 if (!NATIVE_ROOT.equals(entry.getValue())) {
628 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
629 if (resourcefetched != null && resourcefetched.isLeft()) {
630 componentsList.add(resourcefetched.left().value());
634 setImports(imports, dependencies, componentsList);
636 setImports(imports, dependencies, fetchedComponent);
642 * Returns all derived_from nodes found.
644 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
645 final Resource parentResource = (Resource) fetchedComponent;
646 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
647 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
648 componentsList.add(fetchedComponent);
649 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
650 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
651 .getToscaElement(componentInstance.getComponentUid());
652 if (resourcefetched != null && resourcefetched.isLeft()) {
653 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
654 if (MapUtils.isNotEmpty(derivedWithId)) {
655 derivedFromMapOfIdToName.putAll(derivedWithId);
660 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
662 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
663 return Optional.ofNullable(derivedFromMapOfIdToName);
667 * Creates a resource map and adds it to the import list.
669 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
670 final Set<Component> componentsList) {
671 componentsList.forEach(component -> setImports(imports, dependencies, component));
674 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
675 final Component component) {
676 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
677 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
678 if (artifactDefinition != null) {
679 final Map<String, String> files = new HashMap<>();
680 final String artifactName = artifactDefinition.getArtifactName();
681 files.put(IMPORTS_FILE_KEY, artifactName);
682 final StringBuilder keyNameBuilder = new StringBuilder();
683 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
684 keyNameBuilder.append("-");
685 keyNameBuilder.append(component.getName());
686 addImports(imports, keyNameBuilder, files);
687 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
688 if (!ModelConverter.isAtomicComponent(component)) {
689 final Map<String, String> interfaceFiles = new HashMap<>();
690 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
691 keyNameBuilder.append("-interface");
692 addImports(imports, keyNameBuilder, interfaceFiles);
698 * Adds the found resource to the import definition list.
700 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
701 final Map<String, String> files) {
702 final String mapKey = keyNameBuilder.toString();
703 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
704 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
705 importsListMember.put(keyNameBuilder.toString(), files);
706 imports.add(importsListMember);
710 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
711 Map<String, ToscaNodeType> nodeTypes) {
712 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
715 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
716 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
717 boolean isAssociatedComponent) {
718 log.debug("start convert node type for {}", component.getUniqueId());
719 ToscaNodeType toscaNodeType = createNodeType(component);
720 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
721 .getAllInterfaceLifecycleTypes(component.getModel());
722 if (lifecycleTypeEither.isRight()) {
723 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
724 return Either.right(ToscaError.GENERAL_ERROR);
726 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
727 .collect(Collectors.toList());
728 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
729 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
730 if (dataTypesEither.isRight()) {
731 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
732 return Either.right(ToscaError.GENERAL_ERROR);
734 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
735 List<InputDefinition> inputDef = component.getInputs();
736 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
737 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
738 addInputsToProperties(dataTypes, inputDef, mergedProperties);
739 final Map<String, ToscaAttribute> toscaAttributeMap;
740 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
741 if (!toscaAttributeMap.isEmpty()) {
742 toscaNodeType.setAttributes(toscaAttributeMap);
744 if (CollectionUtils.isNotEmpty(component.getProperties())) {
745 List<PropertyDefinition> properties = component.getProperties();
746 Map<String, ToscaProperty> convertedProperties = properties.stream()
747 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
748 .toMap(PropertyDataDefinition::getName,
749 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
750 // merge component properties and inputs properties
751 mergedProperties.putAll(convertedProperties);
753 if (MapUtils.isNotEmpty(mergedProperties)) {
754 toscaNodeType.setProperties(mergedProperties);
756 /* convert private data_types */
757 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
758 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
759 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
760 for (DataTypeDefinition dataType : privateDataTypes) {
761 log.debug("Emitting private data type: component.name={} dataType.name={}",
762 component.getNormalizedName(), dataType.getName());
763 ToscaDataType toscaDataType = new ToscaDataType();
764 toscaDataType.setDerived_from(dataType.getDerivedFromName());
765 toscaDataType.setDescription(dataType.getDescription());
766 toscaDataType.setVersion(dataType.getVersion());
767 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
768 toscaDataType.setProperties(dataType.getProperties().stream()
769 .collect(Collectors.toMap(
770 PropertyDataDefinition::getName,
771 s -> propertyConvertor
772 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
775 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
777 toscaNode.setData_types(toscaDataTypeMap);
780 // Extracted to method for code reuse
781 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
784 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
785 final Map<String, DataTypeDefinition> dataTypes) {
786 if (CollectionUtils.isEmpty(attributeList)) {
787 return Collections.emptyMap();
789 final AttributeConverter converter = new AttributeConverter(dataTypes);
790 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
791 for (final AttributeDefinition attributeDefinition : attributeList) {
792 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
794 return toscaAttributeMap;
797 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
798 Component component, ToscaTemplate toscaNode,
799 Map<String, ToscaNodeType> nodeTypes,
800 ToscaNodeType toscaNodeType,
801 Map<String, DataTypeDefinition> dataTypes) {
802 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
804 if (capabilities.isRight()) {
805 return Either.right(capabilities.right().value());
807 toscaNodeType = capabilities.left().value();
808 log.debug("Capabilities converted for {}", component.getUniqueId());
810 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
811 .convertRequirements(componentsCache, component, toscaNodeType);
812 if (requirements.isRight()) {
813 return Either.right(requirements.right().value());
815 toscaNodeType = requirements.left().value();
816 log.debug("Requirements converted for {}", component.getUniqueId());
818 String toscaResourceName;
819 switch (component.getComponentType()) {
821 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
822 .getMetadataDataDefinition()).getToscaResourceName();
825 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
826 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
829 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
830 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
833 nodeTypes.put(toscaResourceName, toscaNodeType);
834 toscaNode.setNode_types(nodeTypes);
835 log.debug("finish convert node type for {}", component.getUniqueId());
836 return Either.left(toscaNode);
839 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
840 final Map<String, Component> componentCache,
841 final Map<String, DataTypeDefinition> dataTypes,
842 final ToscaTopolgyTemplate topologyTemplate) {
844 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
845 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
846 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
847 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
848 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
850 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
851 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
852 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
854 Map<String, ToscaGroupTemplate> groupsMap = null;
855 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
856 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
857 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
858 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
860 nodeTemplate.setType(componentInstance.getToscaComponentName());
861 nodeTemplate.setDirectives(componentInstance.getDirectives());
862 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
864 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
865 .getOriginComponent(componentCache, componentInstance);
866 if (originComponentRes.isRight()) {
867 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
870 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
871 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
872 if (requirements.isRight()) {
873 convertNodeTemplatesRes = Either.right(requirements.right().value());
876 final String instanceUniqueId = componentInstance.getUniqueId();
877 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
879 nodeTemplate = requirements.left().value();
881 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
883 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
884 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
885 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
887 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
890 final Either<ToscaNodeTemplate, ToscaError> capabilities =
891 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
892 if (capabilities.isRight()) {
893 convertNodeTemplatesRes = Either.right(capabilities.right().value());
896 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
898 nodeTemplate = capabilities.left().value();
899 final Map<String, Object> props = new HashMap<>();
900 final Map<String, Object> attribs = new HashMap<>();
902 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
903 // Adds the properties of parent component to map
904 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
905 addAttributesOfParentComponent(originalComponent, attribs);
908 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
909 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
911 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
912 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
915 if (componentInstancesInputs != null
916 && componentInstancesInputs.containsKey(instanceUniqueId)
917 && !isComponentOfTypeServiceProxy(componentInstance)) {
918 //For service proxy the inputs are already handled under instance properties above
919 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
922 //M3[00001] - NODE TEMPLATE INTERFACES - START
923 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
924 //M3[00001] - NODE TEMPLATE INTERFACES - END
925 if (MapUtils.isNotEmpty(props)) {
926 nodeTemplate.setProperties(props);
928 if (MapUtils.isNotEmpty(attribs)) {
929 nodeTemplate.setAttributes(attribs);
932 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
933 if (CollectionUtils.isNotEmpty(groupInstances)) {
934 if (groupsMap == null) {
935 groupsMap = new HashMap<>();
937 for (final GroupInstance groupInst : groupInstances) {
938 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
939 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
944 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
946 if (groupsMap != null) {
947 log.debug("instance groups added");
948 topologyTemplate.addGroups(groupsMap);
950 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
951 ((Service) component).getForwardingPaths())) {
952 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
953 ForwardingPathToscaUtil
954 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
955 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
957 if (convertNodeTemplatesRes == null) {
958 convertNodeTemplatesRes = Either.left(nodeTemplates);
960 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
961 return convertNodeTemplatesRes;
964 private void handleInstanceInterfaces(
965 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
966 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
967 String instanceUniqueId,
968 Component parentComponent) {
970 if (MapUtils.isEmpty(componentInstanceInterfaces)
971 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
972 nodeTemplate.setInterfaces(null);
976 final List<ComponentInstanceInterface> currServiceInterfaces =
977 componentInstanceInterfaces.get(instanceUniqueId);
979 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
980 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
981 .getUniqueId(), instInterface));
983 final Map<String, Object> interfaceMap = interfacesOperationsConverter
984 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
985 isComponentOfTypeServiceProxy(componentInstance));
987 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
988 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
991 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
992 return Objects.nonNull(componentInstance.getOriginType())
993 && componentInstance.getOriginType().getValue().equals("Service Proxy");
996 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
997 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
998 String instanceUniqueId, Map<String, Object> props) {
1000 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1001 if (instanceInputsList != null) {
1002 instanceInputsList.forEach(input -> {
1003 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
1004 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1009 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1010 final Map<String, DataTypeDefinition> dataTypes,
1011 final String instanceUniqueId,
1012 final Map<String, Object> props) {
1014 if (isNotEmpty(componentInstancesProperties)) {
1015 componentInstancesProperties.get(instanceUniqueId)
1016 // Converts and adds each value to property map
1017 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1021 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1022 final String instanceUniqueId,
1023 final Map<String, Object> attribs) {
1025 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1026 componentInstancesAttributes.get(instanceUniqueId).stream()
1027 // Filters out Attributes with empty default values
1028 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1029 // Converts and adds each value to attribute map
1030 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1034 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1035 Component componentOfInstance, Map<String, Object> props) {
1037 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1038 if (isNotEmpty(componentProperties)) {
1039 componentProperties.stream()
1040 // Filters out properties with empty default values
1041 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1042 // Converts and adds each value to property map
1043 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1047 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1049 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1050 if (isNotEmpty(componentAttributes)) {
1051 componentAttributes.stream()
1052 // Filters out Attributes with empty default values
1053 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1054 // Converts and adds each value to attribute map
1055 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1059 private ToscaNodeType createNodeType(Component component) {
1060 ToscaNodeType toscaNodeType = new ToscaNodeType();
1061 if (ModelConverter.isAtomicComponent(component)) {
1062 if (((Resource) component).getDerivedFrom() != null) {
1063 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1065 toscaNodeType.setDescription(component.getDescription());
1067 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1069 toscaNodeType.setDerived_from(derivedFrom);
1071 return toscaNodeType;
1074 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1076 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1077 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1078 List<ComponentInstance> componentInstances = container.getComponentInstances();
1079 if (CollectionUtils.isEmpty(componentInstances)) {
1082 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1083 componentInstances.stream()
1084 .filter(this::isComponentOfTypeServiceProxy)
1085 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1086 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1089 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1090 Component serviceComponent;
1091 ComponentParametersView componentParametersView = new ComponentParametersView();
1092 componentParametersView.disableAll();
1093 componentParametersView.setIgnoreInterfaces(false);
1094 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1095 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1096 if (service.isRight()) {
1097 log.debug("Failed to fetch original service component with id {} for instance {}",
1098 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1099 return Either.right(ToscaError.GENERAL_ERROR);
1101 serviceComponent = service.left().value();
1104 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1105 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1106 if (lifecycleTypeEither.isRight()) {
1107 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1108 return Either.right(ToscaError.GENERAL_ERROR);
1111 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1112 .map(InterfaceDataDefinition::getType)
1113 .collect(Collectors.toList());
1114 //Add interface types for local interfaces in the original service component for proxy
1115 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1116 allGlobalInterfaceTypes);
1117 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1118 proxyInterfaceTypes.putAll(localInterfaceTypes);
1122 return Either.left(proxyInterfaceTypes);
1125 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1126 Component container) {
1128 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1129 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1131 List<ComponentInstance> componentInstances = container.getComponentInstances();
1133 if (componentInstances == null || componentInstances.isEmpty()) {
1136 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1137 List<ComponentInstance> proxyInst = componentInstances.stream()
1138 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1139 .collect(Collectors.toList());
1140 if (proxyInst != null && !proxyInst.isEmpty()) {
1141 for (ComponentInstance inst : proxyInst) {
1142 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1146 if (serviceProxyInstanceList.isEmpty()) {
1149 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1150 .getLatestByName("serviceProxy", null);
1151 if (serviceProxyOrigin.isRight()) {
1152 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1153 serviceProxyOrigin.right().value());
1154 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1156 Component origComponent = serviceProxyOrigin.left().value();
1158 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1159 Component serviceComponent = null;
1160 ComponentParametersView componentParametersView = new ComponentParametersView();
1161 componentParametersView.disableAll();
1162 componentParametersView.setIgnoreCategories(false);
1163 componentParametersView.setIgnoreProperties(false);
1164 componentParametersView.setIgnoreInputs(false);
1165 componentParametersView.setIgnoreInterfaces(false);
1166 componentParametersView.setIgnoreRequirements(false);
1167 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1168 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1169 if (service.isRight()) {
1170 log.debug("Failed to fetch resource with id {} for instance {}",
1171 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1173 serviceComponent = service.left().value();
1176 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1177 entryProxy.getValue());
1178 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1181 return Either.left(nodeTypesMap);
1184 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1185 final Component container, final ToscaTemplate toscaNode) {
1186 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1188 if (CollectionUtils.isEmpty(componentInstances)) {
1191 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1192 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1193 .collect(Collectors.toList());
1194 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1195 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1196 final Map<String, ToscaNodeType> nodeTypes =
1197 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1198 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1204 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1205 Component proxyComponent, ComponentInstance componentInstance) {
1206 ToscaNodeType toscaNodeType = new ToscaNodeType();
1207 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1209 toscaNodeType.setDerived_from(derivedFrom);
1210 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel());
1211 if (dataTypesEither.isRight()) {
1212 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1214 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1215 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1216 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1218 if (MapUtils.isNotEmpty(capabilities)) {
1219 toscaNodeType.setCapabilities(capabilities);
1221 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1222 .convertProxyRequirements(componentCache, componentInstance);
1223 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1224 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1226 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1227 proxyProperties.ifPresent(toscaNodeType::setProperties);
1229 Map<String, Object> interfaceMap = new HashMap<>();
1230 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1231 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1232 if (proxyInterfaces.isPresent()) {
1233 interfaceMap = proxyInterfaces.get();
1236 interfaceMap = interfacesOperationsConverter
1237 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1240 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1241 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1243 return toscaNodeType;
1246 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1247 ComponentInstance componentInstance,
1248 List<RequirementCapabilityRelDef> relations,
1249 ToscaNodeTemplate nodeTypeTemplate,
1250 Component originComponent,
1251 Map<String, Component> componentCache) {
1253 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1255 if (isNotEmpty(requirementDefinitionList)) {
1257 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1258 if (!toscaRequirements.isEmpty()) {
1259 nodeTypeTemplate.setRequirements(toscaRequirements);
1261 } catch (final Exception e) {
1262 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1263 componentInstance.getName(), e);
1264 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1267 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1268 return Either.left(nodeTypeTemplate);
1271 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1272 final ComponentInstance componentInstance,
1273 final List<RequirementCapabilityRelDef> filteredRelations,
1274 final Component originComponent,
1275 final Map<String, Component> componentCache)
1276 throws ToscaExportException {
1278 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1279 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1280 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1281 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1282 toscaRequirements.add(toscaTemplateRequirementMap);
1285 return toscaRequirements;
1288 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1289 List<RequirementCapabilityRelDef> relations) {
1290 return relations.stream()
1291 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1294 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1295 final Component fromOriginComponent,
1296 final List<ComponentInstance> instancesList,
1297 final RequirementCapabilityRelDef relationshipDefinition,
1298 final Map<String, Component> componentCache)
1299 throws ToscaExportException {
1301 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1302 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1303 .getRelationships().get(0);
1304 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1306 final ComponentInstance toInstance = instancesList.stream()
1307 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1308 .findFirst().orElse(null);
1309 if (toInstance == null) {
1310 final String errorMsg = String
1311 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1312 relationshipDefinition.getToNode());
1313 log.debug(errorMsg);
1314 throw new ToscaExportException(errorMsg);
1316 final Optional<RequirementDefinition> reqOpt =
1317 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1318 if (reqOpt.isEmpty()) {
1319 final String errorMsg = String
1320 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1321 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1322 log.debug(errorMsg);
1323 throw new ToscaExportException(errorMsg);
1325 final ComponentParametersView filter = new ComponentParametersView(true);
1326 filter.setIgnoreComponentInstances(false);
1327 filter.setIgnoreCapabilities(false);
1328 filter.setIgnoreGroups(false);
1329 final Either<Component, StorageOperationStatus> getOriginRes =
1330 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1331 if (getOriginRes.isRight()) {
1332 final String errorMsg = String.format(
1333 "Failed to build substituted name for the requirement %s. "
1334 + "Failed to get an origin component with uniqueId %s",
1335 reqOpt.get().getName(), toInstance.getActualComponentUid());
1336 log.debug(errorMsg);
1337 throw new ToscaExportException(errorMsg);
1339 final Component toOriginComponent = getOriginRes.left().value();
1340 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1341 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1342 if (capOpt.isEmpty()) {
1343 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1344 if (capOpt.isEmpty()) {
1345 final String errorMsg = String
1346 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1347 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1348 log.debug(errorMsg);
1349 throw new ToscaExportException(errorMsg);
1352 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1353 capabilityRequirementRelationship, toInstance, componentCache);
1356 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1357 CapabilityDefinition capability) {
1358 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1359 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1362 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1363 Component toOriginComponent, Component fromOriginComponent,
1364 RequirementDefinition requirement) {
1365 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1366 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1367 if (!cap.isPresent()) {
1368 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1369 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1374 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1375 final Component toOriginComponent,
1376 final CapabilityDefinition capability,
1377 final RequirementDefinition requirement,
1378 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1379 final ComponentInstance toInstance,
1380 final Map<String, Component> componentCache)
1381 throws ToscaExportException {
1383 List<String> reducedPath = capability.getPath();
1384 if (capability.getOwnerId() != null) {
1385 reducedPath = capabilityRequirementConverter
1386 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1388 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1389 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1390 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1391 if (capabilityNameEither.isRight()) {
1392 final String errorMsg = String.format(
1393 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1394 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1397 throw new ToscaExportException(errorMsg);
1399 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1400 .buildSubstitutedName(componentCache, fromOriginComponent,
1401 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1402 if (requirementNameEither.isRight()) {
1403 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1404 + "with name %s on a component with uniqueId %s",
1405 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1406 log.debug(errorMsg);
1407 throw new ToscaExportException(errorMsg);
1409 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1410 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1411 toscaRequirement.setNode(toInstance.getName());
1412 toscaRequirement.setCapability(capabilityNameEither.left().value());
1413 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1414 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1416 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1420 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1421 Map<String, List<RequirementDefinition>> reqMap,
1422 RelationshipInfo reqAndRelationshipPair,
1423 String fromInstanceId) {
1424 for (List<RequirementDefinition> reqList : reqMap.values()) {
1425 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1426 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1428 if (reqOpt.isPresent()) {
1432 return Optional.empty();
1436 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1437 * 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
1438 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1440 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1441 RequirementDefinition requirement, String fromInstanceId) {
1442 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1443 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1444 reqAndRelationshipPair.getRequirement());
1447 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1451 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1452 Component originComponent) {
1453 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1454 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1455 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1458 private boolean isCvfc(Component component) {
1459 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1462 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1463 Map<String, Component> componentCache) {
1464 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1465 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1466 .convertSubstitutionMappingCapabilities(componentCache, component);
1467 if (toscaCapabilitiesRes.isRight()) {
1468 result = Either.right(toscaCapabilitiesRes.right().value());
1469 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1470 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1471 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1472 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1474 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1478 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1479 Map<String, DataTypeDefinition> dataTypes) {
1480 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1481 if (!toscaCapabilities.isEmpty()) {
1482 nodeType.setCapabilities(toscaCapabilities);
1484 log.debug("Finish convert Capabilities for node type");
1485 return Either.left(nodeType);
1488 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1489 if (artifacts == null) {
1492 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1493 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1494 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1495 artifact.setFile(entry.getValue().getFile());
1496 artifact.setType(entry.getValue().getType());
1497 arts.put(entry.getKey(), artifact);
1502 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1503 if (inNodeFilter == null) {
1506 NodeFilter nodeFilter = new NodeFilter();
1507 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1508 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1509 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1510 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1511 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1512 copyNodeFilterProperties(origProperties, propertiesCopy);
1513 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1514 nodeFilter.setCapabilities(capabilitiesCopy);
1516 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1517 nodeFilter.setProperties(propertiesCopy);
1519 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1520 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1524 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1525 if (substitutionFilterDataDefinition == null) {
1528 NodeFilter nodeFilter = new NodeFilter();
1529 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1530 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1531 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1532 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1533 nodeFilter.setProperties(propertiesCopy);
1535 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1536 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1539 private Object cloneToscaId(Object toscaId) {
1540 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1543 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1544 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1545 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1548 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1549 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1550 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1554 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1555 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1556 CapabilityFilter capabilityFilter = new CapabilityFilter();
1557 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1558 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1559 capabilityFilter.setProperties(propertiesCopy);
1560 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1561 capabilitiesCopy.add(capabilityFilterCopyMap);
1565 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1566 List<Map<String, List<Object>>> propertiesCopy) {
1567 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1570 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1571 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1572 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1573 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1574 String propertyName = propertyDataDefinition.getName();
1575 if (propertyMapCopy.containsKey(propertyName)) {
1576 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1578 if (propertyName != null) {
1579 List<Object> propsList = new ArrayList<>();
1580 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1581 propertyMapCopy.put(propertyName, propsList);
1583 propertyMapCopy.putAll(propertyValObj);
1588 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1591 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1592 final List<Map<String, List<Object>>> propertiesCopy) {
1593 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1596 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1597 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1598 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1599 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1600 final String propertyName = propertyDataDefinition.getName();
1601 if (propertyMapCopy.containsKey(propertyName)) {
1602 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1604 if (propertyName != null) {
1605 final List<Object> propsList = new ArrayList<>();
1606 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1607 propertyMapCopy.put(propertyName, propsList);
1609 propertyMapCopy.putAll(propertyValObj);
1614 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1617 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1618 if (propertyValObj.containsKey(propertyName)) {
1619 propsList.add(propertyValObj.get(propertyName));
1621 propsList.add(propertyValObj);
1625 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1626 Map<String, List<Object>> tempMap = new HashMap<>();
1627 tempMap.put(entry.getKey(), entry.getValue());
1628 propertiesCopy.add(tempMap);
1631 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1632 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1633 return Collections.emptyMap();
1635 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1636 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1639 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1640 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1641 return Collections.emptyMap();
1643 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1644 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1647 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1648 if (Objects.isNull(proxyComponent)) {
1649 return Optional.empty();
1651 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1652 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1653 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1654 proxyProperties.putAll(proxyComponent.getProperties().stream()
1655 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1656 .toMap(PropertyDataDefinition::getName,
1657 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1659 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1662 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1663 Map<String, ToscaProperty> mergedProperties) {
1664 if (CollectionUtils.isEmpty(componentInputs)) {
1667 for (InputDefinition input : componentInputs) {
1668 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1669 mergedProperties.put(input.getName(), property);
1673 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1674 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1675 return Optional.empty();
1677 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1678 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1680 // always available in the proxy node template
1681 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1683 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1686 private static class CustomRepresenter extends Representer {
1688 CustomRepresenter() {
1690 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1691 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1692 // null representer is exceptional and it is stored as an instance
1695 this.nullRepresenter = new RepresentNull();
1698 public boolean validateGetInputValue(final Object valueObj) {
1699 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1702 if (valueObj instanceof List) {
1703 return ((List) valueObj).size() > 1;
1708 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1709 if (valueObj instanceof List) {
1710 return ((List) valueObj).size() > 1;
1716 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1717 if (propertyValue == null) {
1720 // skip not relevant for Tosca property
1721 if ("dependencies".equals(property.getName())) {
1724 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1727 removeDefaultP(propertyValue);
1728 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1729 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1730 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1732 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1735 private void removeDefaultP(final Object propertyValue) {
1736 if (propertyValue instanceof Map) {
1737 final Map mapPropertyValue = ((Map) propertyValue);
1738 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1739 Object defaultValue = null;
1740 while (iter.hasNext()) {
1741 final Map.Entry entry = iter.next();
1742 if ("_defaultp_".equals(entry.getKey())) {
1743 defaultValue = entry.getValue();
1745 } else if (entry.getValue() instanceof Map) {
1746 removeDefaultP(entry.getValue());
1749 if (defaultValue != null) {
1750 mapPropertyValue.putIfAbsent("default", defaultValue);
1756 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1757 // remove the bean type from the output yaml (!! ...)
1758 if (!classTags.containsKey(javaBean.getClass())) {
1759 addClassTag(javaBean.getClass(), Tag.MAP);
1761 return super.representJavaBean(properties, javaBean);
1764 private class RepresentToscaAttribute implements Represent {
1767 public Node representData(Object data) {
1768 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1769 return represent(toscaAttribute.asToscaMap());
1773 private class RepresentToscaPropertyAssignment implements Represent {
1775 public Node representData(Object data) {
1776 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1777 if (toscaOperationAssignment.getValue() instanceof String) {
1778 final String stringValue = (String) toscaOperationAssignment.getValue();
1779 if (isPropertyOrAttributeFunction(stringValue)) {
1780 return representGetAttribute(stringValue);
1782 return representScalar(Tag.STR, stringValue);
1784 return represent(null);
1787 public Node representGetAttribute(final String getAttributeFunction) {
1788 return represent(new Yaml().load(getAttributeFunction));
1791 public boolean isPropertyOrAttributeFunction(final String value) {
1793 final Yaml yaml = new Yaml();
1794 final Object yamlObj = yaml.load(value);
1795 if (!(yamlObj instanceof Map)) {
1798 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1799 if (getAttributeMap.size() != 1) {
1802 final List<String> functionList = Arrays
1803 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1804 final Optional<String> function = getAttributeMap.keySet().stream()
1805 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1806 if (function.isEmpty()) {
1809 final String functionName = function.get();
1810 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1811 if (GET_INPUT.getFunctionName().equals(functionName)) {
1812 return validateGetInputValue(getAttributeValueObj);
1814 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1816 } catch (final Exception ignored) {
1822 private class RepresentNull implements Represent {
1825 public Node representData(Object data) {
1826 // possible values are here http://yaml.org/type/null.html
1827 return representScalar(Tag.NULL, "");
1832 private static class UnsortedPropertyUtils extends PropertyUtils {
1835 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1836 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1837 return new LinkedHashSet<>(fields);
1841 private Configuration getConfiguration() {
1842 return ConfigurationManager.getConfigurationManager().getConfiguration();