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.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
29 import com.fasterxml.jackson.databind.ObjectMapper;
30 import com.google.common.primitives.Ints;
31 import com.google.gson.JsonElement;
32 import com.google.gson.JsonObject;
33 import com.google.gson.JsonParser;
34 import com.google.gson.stream.JsonReader;
35 import fj.data.Either;
37 import java.io.StringReader;
38 import java.nio.file.Path;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedHashMap;
47 import java.util.LinkedHashSet;
48 import java.util.List;
50 import java.util.Map.Entry;
51 import java.util.Objects;
52 import java.util.Optional;
54 import java.util.function.Supplier;
55 import java.util.stream.Collectors;
57 import org.apache.commons.collections.CollectionUtils;
58 import org.apache.commons.collections.MapUtils;
59 import org.apache.commons.io.FilenameUtils;
60 import org.apache.commons.lang3.StringUtils;
61 import org.apache.commons.lang3.tuple.ImmutablePair;
62 import org.apache.commons.lang3.tuple.ImmutableTriple;
63 import org.apache.commons.lang3.tuple.Triple;
64 import org.onap.sdc.tosca.services.YamlUtil;
65 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
66 import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
67 import org.openecomp.sdc.be.config.Configuration;
68 import org.openecomp.sdc.be.config.ConfigurationManager;
69 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
70 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
71 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
84 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
85 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
86 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
87 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
88 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
89 import org.openecomp.sdc.be.exception.ToscaExportException;
90 import org.openecomp.sdc.be.model.ArtifactDefinition;
91 import org.openecomp.sdc.be.model.AttributeDefinition;
92 import org.openecomp.sdc.be.model.CapabilityDefinition;
93 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
94 import org.openecomp.sdc.be.model.Component;
95 import org.openecomp.sdc.be.model.ComponentInstance;
96 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
97 import org.openecomp.sdc.be.model.ComponentInstanceInput;
98 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
99 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
100 import org.openecomp.sdc.be.model.ComponentParametersView;
101 import org.openecomp.sdc.be.model.DataTypeDefinition;
102 import org.openecomp.sdc.be.model.GroupInstance;
103 import org.openecomp.sdc.be.model.InputDefinition;
104 import org.openecomp.sdc.be.model.InterfaceDefinition;
105 import org.openecomp.sdc.be.model.PropertyDefinition;
106 import org.openecomp.sdc.be.model.RelationshipInfo;
107 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
108 import org.openecomp.sdc.be.model.RequirementDefinition;
109 import org.openecomp.sdc.be.model.Resource;
110 import org.openecomp.sdc.be.model.Service;
111 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
112 import org.openecomp.sdc.be.model.category.CategoryDefinition;
113 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
114 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
115 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
116 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
117 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
118 import org.openecomp.sdc.be.model.tosca.ToscaType;
119 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
120 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
121 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
122 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
123 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
124 import org.openecomp.sdc.be.tosca.model.NodeFilter;
125 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
126 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
127 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
128 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
129 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
130 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
131 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
132 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
133 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
134 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
135 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
136 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
137 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
138 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
139 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
140 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
141 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
142 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
143 import org.openecomp.sdc.be.tosca.utils.InputConverter;
144 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
145 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
146 import org.openecomp.sdc.common.log.wrappers.Logger;
147 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
148 import org.springframework.beans.factory.annotation.Autowired;
149 import org.yaml.snakeyaml.DumperOptions;
150 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
151 import org.yaml.snakeyaml.Yaml;
152 import org.yaml.snakeyaml.introspector.BeanAccess;
153 import org.yaml.snakeyaml.introspector.Property;
154 import org.yaml.snakeyaml.introspector.PropertyUtils;
155 import org.yaml.snakeyaml.nodes.MappingNode;
156 import org.yaml.snakeyaml.nodes.Node;
157 import org.yaml.snakeyaml.nodes.NodeTuple;
158 import org.yaml.snakeyaml.nodes.Tag;
159 import org.yaml.snakeyaml.representer.Represent;
160 import org.yaml.snakeyaml.representer.Representer;
162 @org.springframework.stereotype.Component("tosca-export-handler")
163 public class ToscaExportHandler {
165 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
166 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
167 private static final String INVARIANT_UUID = "invariantUUID";
168 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
169 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
170 private static final String IMPORTS_FILE_KEY = "file";
171 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
172 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
173 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
174 private static final String NATIVE_ROOT = "tosca.nodes.Root";
175 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
176 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
177 private static final YamlUtil yamlUtil = new YamlUtil();
178 private final ApplicationDataTypeCache applicationDataTypeCache;
179 private final ToscaOperationFacade toscaOperationFacade;
180 private final CapabilityRequirementConverter capabilityRequirementConverter;
181 private final PolicyExportParser policyExportParser;
182 private final GroupExportParser groupExportParser;
183 private final PropertyConvertor propertyConvertor;
184 private final AttributeConverter attributeConverter;
185 private final InputConverter inputConverter;
186 private final OutputConverter outputConverter;
187 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
188 private final InterfacesOperationsConverter interfacesOperationsConverter;
189 private final ModelOperation modelOperation;
192 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
193 final ToscaOperationFacade toscaOperationFacade,
194 final CapabilityRequirementConverter capabilityRequirementConverter,
195 final PolicyExportParser policyExportParser,
196 final GroupExportParser groupExportParser,
197 final PropertyConvertor propertyConvertor,
198 final AttributeConverter attributeConverter,
199 final InputConverter inputConverter,
200 final OutputConverter outputConverter,
201 final InterfaceLifecycleOperation interfaceLifecycleOperation,
202 final InterfacesOperationsConverter interfacesOperationsConverter,
203 final ModelOperation modelOperation) {
204 this.applicationDataTypeCache = applicationDataTypeCache;
205 this.toscaOperationFacade = toscaOperationFacade;
206 this.capabilityRequirementConverter = capabilityRequirementConverter;
207 this.policyExportParser = policyExportParser;
208 this.groupExportParser = groupExportParser;
209 this.propertyConvertor = propertyConvertor;
210 this.attributeConverter = attributeConverter;
211 this.inputConverter = inputConverter;
212 this.outputConverter = outputConverter;
213 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
214 this.interfacesOperationsConverter = interfacesOperationsConverter;
215 this.modelOperation = modelOperation;
218 public static String getInterfaceFilename(String artifactName) {
219 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
222 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
223 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
226 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
227 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
230 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
231 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
234 public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
235 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
238 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
239 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
240 if (CollectionUtils.isEmpty(imports)) {
241 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
242 return Either.right(ToscaError.GENERAL_ERROR);
244 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
245 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
246 .startsWith("org.openecomp.resource.abstract.nodes.")) {
247 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
248 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
249 component.getModel());
250 if (baseType.isLeft() && baseType.left().value() != null) {
251 addDependencies(imports, dependencies, baseType.left().value());
253 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
257 String toscaVersion = null;
258 if (component instanceof Resource) {
259 toscaVersion = ((Resource) component).getToscaVersion();
261 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
262 toscaTemplate.setImports(imports);
263 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
264 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
265 isAssociatedComponent);
266 if (toscaTemplateRes.isRight()) {
267 return Either.right(toscaTemplateRes.right().value());
269 toscaTemplate = toscaTemplateRes.left().value();
270 toscaTemplate.setDependencies(dependencies);
271 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
272 return Either.left(toscaRepresentation);
275 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
276 CustomRepresenter representer = new CustomRepresenter();
277 DumperOptions options = new DumperOptions();
278 options.setAllowReadOnlyProperties(false);
279 options.setPrettyFlow(true);
280 options.setDefaultFlowStyle(FlowStyle.FLOW);
281 options.setCanonical(false);
282 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
283 representer.setPropertyUtils(new UnsortedPropertyUtils());
285 Yaml yaml = new Yaml(representer, options);
286 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
287 String sb = getConfiguration().getHeatEnvArtifactHeader()
289 + getConfiguration().getHeatEnvArtifactFooter();
290 return ToscaRepresentation.make(sb.getBytes(), toscaTemplate);
293 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
294 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
295 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
296 if (fillImports.isRight()) {
297 return Either.right(fillImports.right().value());
299 return Either.left(fillImports.left().value().left);
302 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
303 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
304 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
305 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
306 return Either.right(ToscaError.GENERAL_ERROR);
308 log.trace("start tosca export for {}", component.getUniqueId());
309 String toscaVersion = null;
310 if (component instanceof Resource) {
311 toscaVersion = ((Resource) component).getToscaVersion();
313 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
314 toscaTemplate.setMetadata(convertMetadata(component));
315 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
316 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
317 if (ModelConverter.isAtomicComponent(component)) {
318 log.trace("convert component as node type");
319 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
321 log.trace("convert component as topology template");
322 return convertToscaTemplate(component, toscaTemplate);
326 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
327 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
328 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
331 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
332 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
333 if (dataTypesEither.isRight()) {
334 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
335 return Either.right(ToscaError.GENERAL_ERROR);
337 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
338 if (!dataTypeDefinition.isEmpty()) {
339 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
340 ToscaDataType toscaDataType = new ToscaDataType();
341 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
342 toscaDataType.setDescription(dataTypeDefinition.getDescription());
343 toscaDataType.setVersion(dataTypeDefinition.getVersion());
344 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
345 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
346 .collect(Collectors.toMap(
347 PropertyDataDefinition::getName,
348 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
349 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition,
350 toscaPropertyTobeValidated,
354 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
355 toscaTemplate.setData_types(toscaDataTypeMap);
357 return Either.left(toscaTemplate);
360 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
361 if (modelId == null) {
362 return getDefaultToscaImportConfig();
365 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
366 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
367 final Set<Path> addedPathList = new HashSet<>();
368 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
369 var importPath = Path.of(toscaImportByModel.getFullPath());
370 if (addedPathList.contains(importPath)) {
371 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
373 final String fileName = FilenameUtils.getBaseName(importPath.toString());
374 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
375 addedPathList.add(importPath);
380 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
381 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
382 if (importsRes.isRight()) {
383 return Either.right(importsRes.right().value());
385 toscaNode = importsRes.left().value().left;
386 Map<String, Component> componentCache = importsRes.left().value().right;
387 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
388 if (nodeTypesMapEither.isRight()) {
389 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
390 return Either.right(nodeTypesMapEither.right().value());
392 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
393 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
394 toscaNode.setNode_types(nodeTypesMap);
396 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
397 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
398 if (proxyInterfaceTypesEither.isRight()) {
399 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
400 return Either.right(proxyInterfaceTypesEither.right().value());
402 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
403 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
404 toscaNode.setInterface_types(proxyInterfaceTypes);
406 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
407 if (dataTypesEither.isRight()) {
408 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
409 return Either.right(ToscaError.GENERAL_ERROR);
411 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
412 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
413 List<InputDefinition> inputDef = component.getInputs();
414 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
415 if (!inputs.isEmpty()) {
416 topologyTemplate.setInputs(inputs);
418 final Map<String, ToscaProperty> outputs;
420 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
421 } catch (final ToscaConversionException e) {
422 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
423 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
424 return Either.right(ToscaError.GENERAL_ERROR);
426 if (!outputs.isEmpty()) {
427 topologyTemplate.setOutputs(outputs);
429 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
430 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
431 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
432 if (nodeTemplates.isRight()) {
433 return Either.right(nodeTemplates.right().value());
435 log.debug("node templates converted");
436 topologyTemplate.setNode_templates(nodeTemplates.left().value());
438 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
439 .createFrom(topologyTemplate.getNode_templates());
440 if (!relationshipTemplatesMap.isEmpty()) {
441 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
443 addGroupsToTopologyTemplate(component, topologyTemplate);
445 addPoliciesToTopologyTemplate(component, topologyTemplate);
446 } catch (SdcResourceNotFoundException e) {
447 log.debug("Fail to add policies to topology template:", e);
448 return Either.right(ToscaError.GENERAL_ERROR);
451 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
452 } catch (final ToscaExportException e) {
453 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
454 return Either.right(e.getToscaError());
456 if (!topologyTemplate.isEmpty()) {
457 toscaNode.setTopology_template(topologyTemplate);
459 return Either.left(toscaNode);
462 private Either<String, ToscaError> createComponentToscaName(final Component component) {
463 switch (component.getComponentType()) {
465 final ResourceMetadataDataDefinition resourceMetadata =
466 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
467 return Either.left(resourceMetadata.getToscaResourceName());
469 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
471 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
472 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
476 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
477 final Map<String, Component> componentCache) throws ToscaExportException {
478 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
479 return Optional.empty();
482 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
483 if (toscaResourceNameEither.isRight()) {
484 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
486 final String toscaResourceName = toscaResourceNameEither.left().value();
488 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
489 if (doNotExtendBaseType(component)) {
490 substitutionMapping.setNode_type(component.getDerivedFromGenericType());
492 substitutionMapping.setNode_type(toscaResourceName);
494 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
496 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
497 if (capabilitiesEither.isRight()) {
498 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
500 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
501 if (!capabilityMap.isEmpty()) {
502 substitutionMapping.setCapabilities(capabilityMap);
504 final Either<Map<String, String[]>, ToscaError> requirements =
505 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
506 if (requirements.isRight()) {
507 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
509 final Map<String, String[]> requirementMap = requirements.left().value();
510 if (MapUtils.isNotEmpty(requirementMap)) {
511 substitutionMapping.setRequirements(requirementMap);
514 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
515 if (MapUtils.isNotEmpty(propertyMappingMap)) {
516 substitutionMapping.setProperties(propertyMappingMap);
519 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
520 if (MapUtils.isNotEmpty(attributesMappingMap)) {
521 substitutionMapping.setAttributes(attributesMappingMap);
524 return Optional.of(substitutionMapping);
527 private boolean doNotExtendBaseType(final Component component) {
528 final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig = ConfigurationManager.getConfigurationManager().getConfiguration()
529 .getServiceBaseNodeTypes();
530 List<CategoryDefinition> categories = component.getCategories();
531 if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
532 && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
533 return serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
538 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
539 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
540 return Optional.empty();
543 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
546 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
547 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
548 if (groups != null) {
549 topologyTemplate.addGroups(groups);
553 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
554 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
555 if (policies != null) {
556 topologyTemplate.addPolicies(policies);
560 private Map<String, String> convertMetadata(Component component) {
561 return convertMetadata(component, false, null);
564 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
565 Map<String, String> toscaMetadata = new LinkedHashMap<>();
566 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
567 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
569 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
570 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
571 List<CategoryDefinition> categories = component.getCategories();
572 CategoryDefinition categoryDefinition = categories.get(0);
573 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
574 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
576 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
577 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
578 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
579 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
580 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
581 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
582 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
583 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
584 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
585 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
586 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
587 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
588 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
590 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
593 switch (component.getComponentType()) {
595 Resource resource = (Resource) component;
596 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
597 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
598 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
600 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
602 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
603 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
604 if (resource.getTenant() != null) {
605 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
607 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
608 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
609 toscaMetadata.put(resource.isTopologyTemplate() ? JsonPresentationFields.TEMPLATE_VERSION.getPresentation() : JsonPresentationFields.VERSION.getPresentation(), resource.getVersion());
612 Service service = (Service) component;
613 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
614 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
615 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
616 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
617 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
618 toscaMetadata.put(JsonPresentationFields.TEMPLATE_VERSION.getPresentation(), service.getVersion());
619 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
620 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
623 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
624 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
625 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
629 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
631 for (final String key : component.getCategorySpecificMetadata().keySet()) {
632 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
633 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
636 return toscaMetadata;
639 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
640 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
641 return INVARIANT_UUID;
643 return jsonPresentationField.getPresentation();
646 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
647 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
648 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
649 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
650 return Either.right(ToscaError.GENERAL_ERROR);
652 Map<String, Component> componentCache = new HashMap<>();
653 if (!ModelConverter.isAtomicComponent(component)) {
654 final List<Map<String, Map<String, String>>> additionalImports =
655 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
656 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
657 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
658 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
659 if (!substituteTypeImportEntry.isEmpty()) {
660 additionalImports.add(substituteTypeImportEntry);
662 List<ComponentInstance> componentInstances = component.getComponentInstances();
663 if (componentInstances != null && !componentInstances.isEmpty()) {
664 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
666 toscaTemplate.setDependencies(dependencies);
667 toscaTemplate.setImports(additionalImports);
669 log.debug("currently imports supported for VF and service only");
671 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
674 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
675 final Map<String, ArtifactDefinition> toscaArtifacts) {
676 if (doNotExtendBaseType(component)) {
677 return Collections.emptyMap();
679 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
680 return Collections.emptyMap();
682 if (MapUtils.isEmpty(toscaArtifacts)) {
683 return Collections.emptyMap();
685 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
686 if (artifactDefinition == null) {
687 return Collections.emptyMap();
689 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
690 return Map.of(importEntryName,
691 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
695 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
696 return getConfiguration().getDefaultImports();
699 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
700 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
701 log.debug("createDependency componentCache {}", componentCache);
702 Component componentRI = componentCache.get(componentInstance.getComponentUid());
703 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
704 // all resource must be only once!
705 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
706 if ((resource.isRight()) && (log.isDebugEnabled())) {
707 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
708 componentInstance.getUniqueId());
711 final Component fetchedComponent = resource.left().value();
712 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
713 addDependencies(imports, dependencies, componentRI);
718 * Sets a componentCache from the given component/resource.
720 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
721 final Component fetchedComponent) {
722 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
723 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
724 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
725 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
726 .getToscaFullElement(componentInstance.getSourceModelUid());
727 if (sourceService.isRight() && (log.isDebugEnabled())) {
728 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
729 componentInstance.getUniqueId());
731 final Component fetchedSource = sourceService.left().value();
732 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
733 return fetchedSource;
735 return fetchedComponent;
739 * Retrieves all derived_from nodes and stores it in a predictable order.
741 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
742 final Component fetchedComponent) {
743 final Set<Component> componentsList = new LinkedHashSet<>();
744 if (fetchedComponent instanceof Resource) {
745 log.debug("fetchedComponent is a resource {}", fetchedComponent);
746 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
747 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
748 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
749 log.debug("Started entry.getValue() : {}", entry.getValue());
750 if (!NATIVE_ROOT.equals(entry.getValue())) {
751 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
752 if (resourcefetched != null && resourcefetched.isLeft()) {
753 componentsList.add(resourcefetched.left().value());
757 setImports(imports, dependencies, componentsList);
759 setImports(imports, dependencies, fetchedComponent);
765 * Returns all derived_from nodes found.
767 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
768 final Resource parentResource = (Resource) fetchedComponent;
769 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
770 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
771 componentsList.add(fetchedComponent);
772 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
773 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
774 .getToscaElement(componentInstance.getComponentUid());
775 if (resourcefetched != null && resourcefetched.isLeft()) {
776 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
777 if (MapUtils.isNotEmpty(derivedWithId)) {
778 derivedFromMapOfIdToName.putAll(derivedWithId);
783 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
785 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
786 return Optional.ofNullable(derivedFromMapOfIdToName);
790 * Creates a resource map and adds it to the import list.
792 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
793 final Set<Component> componentsList) {
794 componentsList.forEach(component -> setImports(imports, dependencies, component));
797 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
798 final Component component) {
799 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
800 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
801 if (artifactDefinition != null) {
802 final Map<String, String> files = new HashMap<>();
803 final String artifactName = artifactDefinition.getArtifactName();
804 files.put(IMPORTS_FILE_KEY, artifactName);
805 final StringBuilder keyNameBuilder = new StringBuilder();
806 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
807 keyNameBuilder.append("-");
808 keyNameBuilder.append(component.getName());
809 addImports(imports, keyNameBuilder, files);
810 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
811 if (!ModelConverter.isAtomicComponent(component)) {
812 final Map<String, String> interfaceFiles = new HashMap<>();
813 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
814 keyNameBuilder.append("-interface");
815 addImports(imports, keyNameBuilder, interfaceFiles);
821 * Adds the found resource to the import definition list.
823 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
824 final Map<String, String> files) {
825 final String mapKey = keyNameBuilder.toString();
826 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
827 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
828 importsListMember.put(keyNameBuilder.toString(), files);
829 imports.add(importsListMember);
833 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
834 Map<String, ToscaNodeType> nodeTypes) {
835 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
838 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
839 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
840 boolean isAssociatedComponent) {
841 log.debug("start convert node type for {}", component.getUniqueId());
842 ToscaNodeType toscaNodeType = createNodeType(component);
843 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
844 .getAllInterfaceLifecycleTypes(component.getModel());
845 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
846 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
847 return Either.right(ToscaError.GENERAL_ERROR);
849 if (lifecycleTypeEither.isLeft()) {
850 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
851 .collect(Collectors.toList());
852 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
854 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
855 if (dataTypesEither.isRight()) {
856 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
857 return Either.right(ToscaError.GENERAL_ERROR);
859 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
860 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
861 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
862 if (!toscaAttributeMap.isEmpty()) {
863 toscaNodeType.setAttributes(toscaAttributeMap);
865 Map<String, ToscaProperty> convertedProperties = new HashMap();
866 if (CollectionUtils.isNotEmpty(component.getProperties())) {
867 List<PropertyDefinition> properties = component.getProperties();
868 convertedProperties = properties.stream()
869 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
870 .toMap(PropertyDataDefinition::getName,
871 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
873 if (MapUtils.isNotEmpty(convertedProperties)) {
874 toscaNodeType.setProperties(convertedProperties);
876 /* convert private data_types */
877 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
878 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
879 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
880 for (DataTypeDefinition dataType : privateDataTypes) {
881 log.debug("Emitting private data type: component.name={} dataType.name={}",
882 component.getNormalizedName(), dataType.getName());
883 ToscaDataType toscaDataType = new ToscaDataType();
884 toscaDataType.setDerived_from(dataType.getDerivedFromName());
885 toscaDataType.setDescription(dataType.getDescription());
886 toscaDataType.setVersion(dataType.getVersion());
887 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
888 toscaDataType.setProperties(dataType.getProperties().stream()
889 .collect(Collectors.toMap(
890 PropertyDataDefinition::getName,
891 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
892 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
896 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
898 toscaNode.setData_types(toscaDataTypeMap);
901 // Extracted to method for code reuse
902 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
905 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
906 final ToscaProperty toscaProperty) {
907 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
908 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
909 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
912 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
913 final Map<String, DataTypeDefinition> dataTypes) {
914 if (CollectionUtils.isEmpty(attributeList)) {
915 return Collections.emptyMap();
917 final AttributeConverter converter = new AttributeConverter(dataTypes);
918 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
919 for (final AttributeDefinition attributeDefinition : attributeList) {
920 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
922 return toscaAttributeMap;
925 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
926 Component component, ToscaTemplate toscaNode,
927 Map<String, ToscaNodeType> nodeTypes,
928 ToscaNodeType toscaNodeType,
929 Map<String, DataTypeDefinition> dataTypes) {
930 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
932 if (capabilities.isRight()) {
933 return Either.right(capabilities.right().value());
935 toscaNodeType = capabilities.left().value();
936 log.debug("Capabilities converted for {}", component.getUniqueId());
938 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
939 .convertRequirements(componentsCache, component, toscaNodeType);
940 if (requirements.isRight()) {
941 return Either.right(requirements.right().value());
943 toscaNodeType = requirements.left().value();
944 log.debug("Requirements converted for {}", component.getUniqueId());
946 String toscaResourceName;
947 switch (component.getComponentType()) {
949 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
950 .getMetadataDataDefinition()).getToscaResourceName();
953 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
954 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
957 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
958 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
961 nodeTypes.put(toscaResourceName, toscaNodeType);
962 toscaNode.setNode_types(nodeTypes);
963 log.debug("finish convert node type for {}", component.getUniqueId());
964 return Either.left(toscaNode);
967 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
968 final Map<String, Component> componentCache,
969 final Map<String, DataTypeDefinition> dataTypes,
970 final ToscaTopolgyTemplate topologyTemplate) {
972 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
973 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
974 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
975 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
976 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
978 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
979 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
980 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
982 Map<String, ToscaGroupTemplate> groupsMap = null;
983 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
984 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
985 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
986 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
988 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
989 List<Object> occur = new ArrayList<>();
990 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
991 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
992 nodeTemplate.setOccurrences(occur);
994 if (componentInstance.getInstanceCount() != null) {
995 ObjectMapper objectMapper = new ObjectMapper();
996 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
998 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
999 nodeTemplate.setInstance_count(map);
1002 nodeTemplate.setType(componentInstance.getToscaComponentName());
1003 nodeTemplate.setDirectives(componentInstance.getDirectives());
1004 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1005 if (nodeFilter != null && nodeFilter.hasData()) {
1006 nodeTemplate.setNode_filter(nodeFilter);
1008 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1009 .getOriginComponent(componentCache, componentInstance);
1010 if (originComponentRes.isRight()) {
1011 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1014 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1015 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1016 if (requirements.isRight()) {
1017 convertNodeTemplatesRes = Either.right(requirements.right().value());
1020 final String instanceUniqueId = componentInstance.getUniqueId();
1021 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1023 nodeTemplate = requirements.left().value();
1025 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1027 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1028 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1029 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1031 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1034 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1035 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1036 if (capabilities.isRight()) {
1037 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1040 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1042 nodeTemplate = capabilities.left().value();
1043 final Map<String, Object> props = new HashMap<>();
1044 final Map<String, Object> attribs = new HashMap<>();
1046 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1047 // Adds the properties of parent component to map
1048 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1049 addAttributesOfParentComponent(originalComponent, attribs);
1052 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1053 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1055 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1056 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1059 if (componentInstancesInputs != null
1060 && componentInstancesInputs.containsKey(instanceUniqueId)
1061 && !isComponentOfTypeServiceProxy(componentInstance)) {
1062 //For service proxy the inputs are already handled under instance properties above
1063 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1066 //M3[00001] - NODE TEMPLATE INTERFACES - START
1067 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1068 //M3[00001] - NODE TEMPLATE INTERFACES - END
1069 if (MapUtils.isNotEmpty(props)) {
1070 nodeTemplate.setProperties(props);
1072 if (MapUtils.isNotEmpty(attribs)) {
1073 nodeTemplate.setAttributes(attribs);
1076 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1077 if (CollectionUtils.isNotEmpty(groupInstances)) {
1078 if (groupsMap == null) {
1079 groupsMap = new HashMap<>();
1081 for (final GroupInstance groupInst : groupInstances) {
1082 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1083 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1088 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1090 if (groupsMap != null) {
1091 log.debug("instance groups added");
1092 topologyTemplate.addGroups(groupsMap);
1094 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1095 ((Service) component).getForwardingPaths())) {
1096 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1097 ForwardingPathToscaUtil
1098 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1099 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1101 if (convertNodeTemplatesRes == null) {
1102 convertNodeTemplatesRes = Either.left(nodeTemplates);
1104 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1105 return convertNodeTemplatesRes;
1108 private Object convertToToscaObject(String value) {
1110 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1111 StringReader reader = new StringReader(value);
1112 JsonReader jsonReader = new JsonReader(reader);
1113 jsonReader.setLenient(true);
1114 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1115 if (jsonElement.isJsonObject()) {
1116 JsonObject jsonObj = jsonElement.getAsJsonObject();
1117 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1118 return mapConverterInst.handleComplexJsonValue(jsonElement);
1122 } catch (Exception e) {
1123 log.debug("convertToToscaValue failed to parse json value :", e);
1128 private Object parseToIntIfPossible(final String value) {
1129 final Integer intValue = Ints.tryParse(value);
1130 return intValue == null ? value : intValue;
1133 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1134 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1135 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1137 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1138 nodeTemplate.setInterfaces(null);
1142 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1144 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1145 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1147 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1148 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1150 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1151 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1154 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1155 return Objects.nonNull(componentInstance.getOriginType())
1156 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1159 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1160 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1161 String instanceUniqueId, Map<String, Object> props) {
1163 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1164 if (instanceInputsList != null) {
1165 instanceInputsList.forEach(input -> {
1166 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1167 : input.getDefaultValue();
1168 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1173 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1174 final Map<String, DataTypeDefinition> dataTypes,
1175 final String instanceUniqueId,
1176 final Map<String, Object> props) {
1178 if (isNotEmpty(componentInstancesProperties)) {
1179 componentInstancesProperties.get(instanceUniqueId)
1180 // Converts and adds each value to property map
1181 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1185 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1186 final String instanceUniqueId,
1187 final Map<String, Object> attribs) {
1189 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1190 componentInstancesAttributes.get(instanceUniqueId)
1191 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1195 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1196 Component componentOfInstance, Map<String, Object> props) {
1198 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1199 if (isNotEmpty(componentProperties)) {
1200 componentProperties.stream()
1201 // Filters out properties with empty default values
1202 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1203 // Converts and adds each value to property map
1204 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1208 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1210 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1211 if (isNotEmpty(componentAttributes)) {
1212 componentAttributes.stream()
1213 // Filters out Attributes with empty default values
1214 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1215 // Converts and adds each value to attribute map
1216 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1220 private ToscaNodeType createNodeType(Component component) {
1221 ToscaNodeType toscaNodeType = new ToscaNodeType();
1222 if (ModelConverter.isAtomicComponent(component)) {
1223 if (((Resource) component).getDerivedFrom() != null) {
1224 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1226 toscaNodeType.setDescription(component.getDescription());
1228 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1230 toscaNodeType.setDerived_from(derivedFrom);
1232 return toscaNodeType;
1235 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1237 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1238 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1239 List<ComponentInstance> componentInstances = container.getComponentInstances();
1240 if (CollectionUtils.isEmpty(componentInstances)) {
1243 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1244 componentInstances.stream()
1245 .filter(this::isComponentOfTypeServiceProxy)
1246 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1247 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1250 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1251 Component serviceComponent;
1252 ComponentParametersView componentParametersView = new ComponentParametersView();
1253 componentParametersView.disableAll();
1254 componentParametersView.setIgnoreInterfaces(false);
1255 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1256 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1257 if (service.isRight()) {
1258 log.debug("Failed to fetch original service component with id {} for instance {}",
1259 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1260 return Either.right(ToscaError.GENERAL_ERROR);
1262 serviceComponent = service.left().value();
1265 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1266 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1267 if (lifecycleTypeEither.isRight()) {
1268 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1269 return Either.right(ToscaError.GENERAL_ERROR);
1272 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1273 .map(InterfaceDataDefinition::getType)
1274 .collect(Collectors.toList());
1275 //Add interface types for local interfaces in the original service component for proxy
1276 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1277 allGlobalInterfaceTypes);
1278 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1279 proxyInterfaceTypes.putAll(localInterfaceTypes);
1283 return Either.left(proxyInterfaceTypes);
1286 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1287 Component container) {
1289 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1290 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1292 List<ComponentInstance> componentInstances = container.getComponentInstances();
1294 if (componentInstances == null || componentInstances.isEmpty()) {
1297 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1298 List<ComponentInstance> proxyInst = componentInstances.stream()
1299 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1300 .collect(Collectors.toList());
1301 if (proxyInst != null && !proxyInst.isEmpty()) {
1302 for (ComponentInstance inst : proxyInst) {
1303 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1307 if (serviceProxyInstanceList.isEmpty()) {
1310 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1311 .getLatestByName("serviceProxy", null);
1312 if (serviceProxyOrigin.isRight()) {
1313 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1314 serviceProxyOrigin.right().value());
1315 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1317 Component origComponent = serviceProxyOrigin.left().value();
1319 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1320 Component serviceComponent = null;
1321 ComponentParametersView componentParametersView = new ComponentParametersView();
1322 componentParametersView.disableAll();
1323 componentParametersView.setIgnoreCategories(false);
1324 componentParametersView.setIgnoreProperties(false);
1325 componentParametersView.setIgnoreInputs(false);
1326 componentParametersView.setIgnoreInterfaces(false);
1327 componentParametersView.setIgnoreRequirements(false);
1328 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1329 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1330 if (service.isRight()) {
1331 log.debug("Failed to fetch resource with id {} for instance {}",
1332 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1334 serviceComponent = service.left().value();
1337 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1338 entryProxy.getValue());
1339 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1342 return Either.left(nodeTypesMap);
1345 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1346 final Component container, final ToscaTemplate toscaNode) {
1347 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1349 if (CollectionUtils.isEmpty(componentInstances)) {
1352 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1353 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1354 .collect(Collectors.toList());
1355 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1356 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1357 final Map<String, ToscaNodeType> nodeTypes =
1358 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1359 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1365 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1366 Component proxyComponent, ComponentInstance componentInstance) {
1367 ToscaNodeType toscaNodeType = new ToscaNodeType();
1368 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1370 toscaNodeType.setDerived_from(derivedFrom);
1371 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1372 origComponent.getModel());
1373 if (dataTypesEither.isRight()) {
1374 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1376 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1377 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1378 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1380 if (MapUtils.isNotEmpty(capabilities)) {
1381 toscaNodeType.setCapabilities(capabilities);
1383 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1384 .convertProxyRequirements(componentCache, componentInstance);
1385 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1386 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1388 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1389 proxyProperties.ifPresent(toscaNodeType::setProperties);
1391 Map<String, Object> interfaceMap = new HashMap<>();
1392 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1393 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1394 if (proxyInterfaces.isPresent()) {
1395 interfaceMap = proxyInterfaces.get();
1398 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1401 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1402 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1404 return toscaNodeType;
1407 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1408 ComponentInstance componentInstance,
1409 List<RequirementCapabilityRelDef> relations,
1410 ToscaNodeTemplate nodeTypeTemplate,
1411 Component originComponent,
1412 Map<String, Component> componentCache) {
1414 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1416 if (isNotEmpty(requirementDefinitionList)) {
1418 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1419 requirementDefinitionList, originComponent, componentCache);
1420 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1421 nodeTypeTemplate.setRequirements(toscaRequirements);
1423 } catch (final Exception e) {
1424 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1425 componentInstance.getName(), e);
1426 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1429 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1430 return Either.left(nodeTypeTemplate);
1433 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1434 final ComponentInstance componentInstance,
1435 final List<RequirementCapabilityRelDef> filteredRelations,
1436 final Component originComponent,
1437 final Map<String, Component> componentCache)
1438 throws ToscaExportException {
1440 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1441 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1442 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1443 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1444 if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1445 toscaRequirements.add(toscaTemplateRequirementMap);
1449 return toscaRequirements;
1452 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1453 List<RequirementCapabilityRelDef> relations) {
1454 return relations.stream()
1455 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1458 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1459 final Component fromOriginComponent,
1460 final List<ComponentInstance> instancesList,
1461 final RequirementCapabilityRelDef relationshipDefinition,
1462 final Map<String, Component> componentCache)
1463 throws ToscaExportException {
1465 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1466 if (MapUtils.isEmpty(reqMap)) {
1467 return new HashMap<>();
1469 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1470 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1472 final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1473 .findFirst().orElse(null);
1474 if (toInstance == null) {
1475 final String errorMsg = String
1476 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1477 relationshipDefinition.getToNode());
1478 log.debug(errorMsg);
1479 throw new ToscaExportException(errorMsg);
1481 final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1482 if (reqOpt.isEmpty()) {
1483 final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1484 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1485 log.debug(errorMsg);
1486 throw new ToscaExportException(errorMsg);
1488 final ComponentParametersView filter = new ComponentParametersView(true);
1489 filter.setIgnoreComponentInstances(false);
1490 filter.setIgnoreCapabilities(false);
1491 filter.setIgnoreGroups(false);
1492 final Either<Component, StorageOperationStatus> getOriginRes =
1493 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1494 if (getOriginRes.isRight()) {
1495 final String errorMsg = String.format(
1496 "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1497 reqOpt.get().getName(), toInstance.getActualComponentUid());
1498 log.debug(errorMsg);
1499 throw new ToscaExportException(errorMsg);
1501 final Component toOriginComponent = getOriginRes.left().value();
1502 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1503 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1504 if (capOpt.isEmpty()) {
1505 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1506 if (capOpt.isEmpty()) {
1507 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1508 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1509 log.debug(errorMsg);
1510 throw new ToscaExportException(errorMsg);
1513 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1514 capabilityRequirementRelationship, toInstance, componentCache);
1517 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1518 CapabilityDefinition capability) {
1519 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1520 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1523 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1524 Component toOriginComponent, Component fromOriginComponent,
1525 RequirementDefinition requirement) {
1526 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1527 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1528 if (cap.isEmpty()) {
1529 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1530 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1535 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1536 final Component toOriginComponent,
1537 final CapabilityDefinition capability,
1538 final RequirementDefinition requirement,
1539 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1540 final ComponentInstance toInstance,
1541 final Map<String, Component> componentCache)
1542 throws ToscaExportException {
1544 List<String> reducedPath = capability.getPath();
1545 if (capability.getOwnerId() != null) {
1546 reducedPath = capabilityRequirementConverter
1547 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1549 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1550 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1551 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1552 if (capabilityNameEither.isRight()) {
1553 final String errorMsg = String.format(
1554 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1555 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1558 throw new ToscaExportException(errorMsg);
1560 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1561 .buildSubstitutedName(componentCache, fromOriginComponent,
1562 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1563 if (requirementNameEither.isRight()) {
1564 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1565 + "with name %s on a component with uniqueId %s",
1566 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1567 log.debug(errorMsg);
1568 throw new ToscaExportException(errorMsg);
1570 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1571 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1572 toscaRequirement.setNode(toInstance.getName());
1573 toscaRequirement.setCapability(capabilityNameEither.left().value());
1574 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1575 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1577 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1581 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1582 Map<String, List<RequirementDefinition>> reqMap,
1583 RelationshipInfo reqAndRelationshipPair,
1584 String fromInstanceId) {
1585 for (final List<RequirementDefinition> reqList : reqMap.values()) {
1586 final Optional<RequirementDefinition> reqOpt = reqList.stream()
1587 .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1588 if (reqOpt.isPresent()) {
1592 return Optional.empty();
1596 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1597 * 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
1598 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1600 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1601 RequirementDefinition requirement, String fromInstanceId) {
1602 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1605 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1606 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1607 reqAndRelationshipPair.getRequirement());
1610 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1614 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1615 Component originComponent) {
1616 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1617 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1618 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1621 private boolean isCvfc(Component component) {
1622 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1625 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1626 final Map<String, Component> componentCache) {
1627 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1628 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1629 if (toscaCapabilitiesRes.isRight()) {
1630 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1631 return Either.right(toscaCapabilitiesRes.right().value());
1633 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1634 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1635 return Either.left(toscaCapabilitiesRes.left().value());
1637 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1639 return Either.left(Collections.emptyMap());
1642 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1643 Map<String, DataTypeDefinition> dataTypes) {
1644 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1645 if (!toscaCapabilities.isEmpty()) {
1646 nodeType.setCapabilities(toscaCapabilities);
1648 log.debug("Finish convert Capabilities for node type");
1649 return Either.left(nodeType);
1652 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1653 if (artifacts == null) {
1656 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1657 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1658 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1659 artifact.setFile(entry.getValue().getFile());
1660 artifact.setType(entry.getValue().getType());
1661 artifact.setProperties(entry.getValue().getProperties());
1662 arts.put(entry.getKey(), artifact);
1667 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1668 if (inNodeFilter == null) {
1671 NodeFilter nodeFilter = new NodeFilter();
1672 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1673 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1674 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1675 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1676 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1677 nodeFilter.setCapabilities(capabilitiesCopy);
1679 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1680 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1681 nodeFilter.setProperties(propertiesCopy);
1683 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1684 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1688 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1689 if (substitutionFilterDataDefinition == null) {
1692 NodeFilter nodeFilter = new NodeFilter();
1693 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1694 if (!propertiesCopy.isEmpty()) {
1695 nodeFilter.setProperties(propertiesCopy);
1697 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1698 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1701 private Object cloneToscaId(Object toscaId) {
1702 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1705 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1706 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1707 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1710 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1711 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1712 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1716 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1717 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1718 final var capabilityFilter = new CapabilityFilter();
1719 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1720 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1721 capabilitiesCopy.add(capabilityFilterCopyMap);
1725 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1726 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1727 return Collections.emptyList();
1729 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1730 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1731 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1732 final String propertyName = propertyFilter.getName();
1733 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1734 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1735 if (constraints == null) {
1736 constraints = new ArrayList<>();
1738 constraints.add(buildNodeFilterValue(filterConstraint));
1743 propertyFilterDefinitionMap.entrySet().stream()
1744 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1745 .forEach(propertiesCopy::add);
1746 return propertiesCopy;
1749 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1750 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1752 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1753 return Collections.emptyList();
1755 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1756 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1757 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1758 final String propertyName = propertyFilter.getName();
1759 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1760 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1761 if (constraints == null) {
1762 constraints = new ArrayList<>();
1764 constraints.add(buildNodeFilterValue(filterConstraint));
1769 propertyFilterDefinitionMap.entrySet().stream()
1770 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1771 .forEach(propertiesCopy::add);
1772 return propertiesCopy;
1775 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1776 if (filterConstraint.getValue() instanceof ToscaFunction) {
1777 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1779 if (filterConstraint.getValue() instanceof List) {
1780 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1781 List<Object> toscaFunctionList = new ArrayList<>();
1782 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1783 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1784 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1787 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1788 ToscaType toscaType = ToscaType.getToscaType(
1789 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1790 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1791 } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1792 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1793 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1794 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1796 if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1797 filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1798 String.valueOf(filterConstraint.getValue())));
1800 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1803 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1804 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1805 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1808 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1811 private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1812 return ToscaType.BOOLEAN.getType().equals(propertyType);
1815 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1816 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1817 return Collections.emptyMap();
1819 Map<String, String[]> propertyMapping = new HashMap<>();
1820 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1821 Collectors.toList());
1823 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1824 propertyMappedInputList.forEach(inputDefinition -> {
1825 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1826 Optional<PropertyDefinition> property = component.getProperties().stream()
1827 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1828 if (property.isPresent()) {
1829 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1832 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1836 return propertyMapping;
1839 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1840 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1841 return Collections.emptyMap();
1843 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1844 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1847 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1848 if (Objects.isNull(proxyComponent)) {
1849 return Optional.empty();
1851 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1852 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1853 proxyProperties.putAll(proxyComponent.getProperties().stream()
1854 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1855 .toMap(PropertyDataDefinition::getName,
1856 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1858 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1861 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1862 String componentUniqueId) {
1863 if (CollectionUtils.isEmpty(componentInputs)) {
1864 return new HashMap<>();
1866 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1867 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1870 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1871 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1872 return Optional.empty();
1874 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1875 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1877 // always available in the proxy node template
1878 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1879 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1882 private Configuration getConfiguration() {
1883 return ConfigurationManager.getConfigurationManager().getConfiguration();
1886 private static class CustomRepresenter extends Representer {
1888 CustomRepresenter() {
1890 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1891 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1892 // null representer is exceptional and it is stored as an instance
1895 this.nullRepresenter = new RepresentNull();
1898 public boolean validateGetInputValue(final Object valueObj) {
1899 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1902 if (valueObj instanceof List) {
1903 return ((List) valueObj).size() > 1;
1908 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1909 if (valueObj instanceof List) {
1910 return ((List) valueObj).size() > 1;
1916 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1917 if (propertyValue == null) {
1920 // skip not relevant for Tosca property
1921 if ("dependencies".equals(property.getName())) {
1924 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1927 if (javaBean instanceof ToscaPropertyConstraint) {
1928 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1930 removeDefaultP(propertyValue);
1931 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1932 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1933 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1935 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1938 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1939 final Tag customTag) {
1940 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1941 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1942 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1945 private void removeDefaultP(final Object propertyValue) {
1946 if (propertyValue instanceof Map) {
1947 final Map mapPropertyValue = ((Map) propertyValue);
1948 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1949 Object defaultValue = null;
1950 while (iter.hasNext()) {
1951 final Map.Entry entry = iter.next();
1952 if ("_defaultp_".equals(entry.getKey())) {
1953 defaultValue = entry.getValue();
1955 } else if (entry.getValue() instanceof Map) {
1956 removeDefaultP(entry.getValue());
1959 if (defaultValue != null) {
1960 mapPropertyValue.putIfAbsent("default", defaultValue);
1966 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1967 // remove the bean type from the output yaml (!! ...)
1968 if (!classTags.containsKey(javaBean.getClass())) {
1969 addClassTag(javaBean.getClass(), Tag.MAP);
1971 return super.representJavaBean(properties, javaBean);
1974 private class RepresentToscaAttribute implements Represent {
1977 public Node representData(Object data) {
1978 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1979 return represent(toscaAttribute.asToscaMap());
1983 private class RepresentToscaPropertyAssignment implements Represent {
1985 public Node representData(Object data) {
1986 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1987 if (toscaOperationAssignment.getValue() instanceof String) {
1988 final String stringValue = (String) toscaOperationAssignment.getValue();
1989 if (isPropertyOrAttributeFunction(stringValue)) {
1990 return representGetAttribute(stringValue);
1992 return representScalar(Tag.STR, stringValue);
1994 return represent(null);
1997 public Node representGetAttribute(final String getAttributeFunction) {
1998 return represent(new Yaml().load(getAttributeFunction));
2001 public boolean isPropertyOrAttributeFunction(final String value) {
2003 final Yaml yaml = new Yaml();
2004 final Object yamlObj = yaml.load(value);
2005 if (!(yamlObj instanceof Map)) {
2008 final Map<String, Object> getAttributeMap = (Map) yamlObj;
2009 if (getAttributeMap.size() != 1) {
2012 final List<String> functionList = Arrays
2013 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2014 final Optional<String> function = getAttributeMap.keySet().stream()
2015 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2016 if (function.isEmpty()) {
2019 final String functionName = function.get();
2020 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2021 if (GET_INPUT.getFunctionName().equals(functionName)) {
2022 return validateGetInputValue(getAttributeValueObj);
2024 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2026 } catch (final Exception ignored) {
2032 private class RepresentNull implements Represent {
2035 public Node representData(Object data) {
2036 // possible values are here http://yaml.org/type/null.html
2037 return representScalar(Tag.NULL, "");
2042 private static class UnsortedPropertyUtils extends PropertyUtils {
2045 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2046 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2047 return new LinkedHashSet<>(fields);