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, Object> convertMetadata(Component component) {
561 return convertMetadata(component, false, null);
564 private Map<String, Object> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
565 Map<String, Object> 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());
622 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming());
623 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
627 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
629 for (final String key : component.getCategorySpecificMetadata().keySet()) {
630 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
631 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
634 return toscaMetadata;
637 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
638 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
639 return INVARIANT_UUID;
641 return jsonPresentationField.getPresentation();
644 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
645 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
646 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
647 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
648 return Either.right(ToscaError.GENERAL_ERROR);
650 Map<String, Component> componentCache = new HashMap<>();
651 if (!ModelConverter.isAtomicComponent(component)) {
652 final List<Map<String, Map<String, String>>> additionalImports =
653 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
654 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
655 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
656 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
657 if (!substituteTypeImportEntry.isEmpty()) {
658 additionalImports.add(substituteTypeImportEntry);
660 List<ComponentInstance> componentInstances = component.getComponentInstances();
661 if (componentInstances != null && !componentInstances.isEmpty()) {
662 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
664 toscaTemplate.setDependencies(dependencies);
665 toscaTemplate.setImports(additionalImports);
667 log.debug("currently imports supported for VF and service only");
669 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
672 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
673 final Map<String, ArtifactDefinition> toscaArtifacts) {
674 if (doNotExtendBaseType(component)) {
675 return Collections.emptyMap();
677 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
678 return Collections.emptyMap();
680 if (MapUtils.isEmpty(toscaArtifacts)) {
681 return Collections.emptyMap();
683 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
684 if (artifactDefinition == null) {
685 return Collections.emptyMap();
687 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
688 return Map.of(importEntryName,
689 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
693 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
694 return getConfiguration().getDefaultImports();
697 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
698 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
699 log.debug("createDependency componentCache {}", componentCache);
700 Component componentRI = componentCache.get(componentInstance.getComponentUid());
701 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
702 // all resource must be only once!
703 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
704 if ((resource.isRight()) && (log.isDebugEnabled())) {
705 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
706 componentInstance.getUniqueId());
709 final Component fetchedComponent = resource.left().value();
710 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
711 addDependencies(imports, dependencies, componentRI);
716 * Sets a componentCache from the given component/resource.
718 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
719 final Component fetchedComponent) {
720 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
721 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
722 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
723 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
724 .getToscaFullElement(componentInstance.getSourceModelUid());
725 if (sourceService.isRight() && (log.isDebugEnabled())) {
726 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
727 componentInstance.getUniqueId());
729 final Component fetchedSource = sourceService.left().value();
730 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
731 return fetchedSource;
733 return fetchedComponent;
737 * Retrieves all derived_from nodes and stores it in a predictable order.
739 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
740 final Component fetchedComponent) {
741 final Set<Component> componentsList = new LinkedHashSet<>();
742 if (fetchedComponent instanceof Resource) {
743 log.debug("fetchedComponent is a resource {}", fetchedComponent);
744 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
745 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
746 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
747 log.debug("Started entry.getValue() : {}", entry.getValue());
748 if (!NATIVE_ROOT.equals(entry.getValue())) {
749 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
750 if (resourcefetched != null && resourcefetched.isLeft()) {
751 componentsList.add(resourcefetched.left().value());
755 setImports(imports, dependencies, componentsList);
757 setImports(imports, dependencies, fetchedComponent);
763 * Returns all derived_from nodes found.
765 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
766 final Resource parentResource = (Resource) fetchedComponent;
767 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
768 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
769 componentsList.add(fetchedComponent);
770 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
771 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
772 .getToscaElement(componentInstance.getComponentUid());
773 if (resourcefetched != null && resourcefetched.isLeft()) {
774 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
775 if (MapUtils.isNotEmpty(derivedWithId)) {
776 derivedFromMapOfIdToName.putAll(derivedWithId);
781 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
783 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
784 return Optional.ofNullable(derivedFromMapOfIdToName);
788 * Creates a resource map and adds it to the import list.
790 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
791 final Set<Component> componentsList) {
792 componentsList.forEach(component -> setImports(imports, dependencies, component));
795 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
796 final Component component) {
797 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
798 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
799 if (artifactDefinition != null) {
800 final Map<String, String> files = new HashMap<>();
801 final String artifactName = artifactDefinition.getArtifactName();
802 files.put(IMPORTS_FILE_KEY, artifactName);
803 final StringBuilder keyNameBuilder = new StringBuilder();
804 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
805 keyNameBuilder.append("-");
806 keyNameBuilder.append(component.getName());
807 addImports(imports, keyNameBuilder, files);
808 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
809 if (!ModelConverter.isAtomicComponent(component)) {
810 final Map<String, String> interfaceFiles = new HashMap<>();
811 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
812 keyNameBuilder.append("-interface");
813 addImports(imports, keyNameBuilder, interfaceFiles);
819 * Adds the found resource to the import definition list.
821 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
822 final Map<String, String> files) {
823 final String mapKey = keyNameBuilder.toString();
824 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
825 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
826 importsListMember.put(keyNameBuilder.toString(), files);
827 imports.add(importsListMember);
831 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
832 Map<String, ToscaNodeType> nodeTypes) {
833 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
836 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
837 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
838 boolean isAssociatedComponent) {
839 log.debug("start convert node type for {}", component.getUniqueId());
840 ToscaNodeType toscaNodeType = createNodeType(component);
841 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
842 .getAllInterfaceLifecycleTypes(component.getModel());
843 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
844 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
845 return Either.right(ToscaError.GENERAL_ERROR);
847 if (lifecycleTypeEither.isLeft()) {
848 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
849 .collect(Collectors.toList());
850 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
852 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
853 if (dataTypesEither.isRight()) {
854 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
855 return Either.right(ToscaError.GENERAL_ERROR);
857 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
858 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
859 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
860 if (!toscaAttributeMap.isEmpty()) {
861 toscaNodeType.setAttributes(toscaAttributeMap);
863 Map<String, ToscaProperty> convertedProperties = new HashMap();
864 if (CollectionUtils.isNotEmpty(component.getProperties())) {
865 List<PropertyDefinition> properties = component.getProperties();
866 convertedProperties = properties.stream()
867 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
868 .toMap(PropertyDataDefinition::getName,
869 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
871 if (MapUtils.isNotEmpty(convertedProperties)) {
872 toscaNodeType.setProperties(convertedProperties);
874 /* convert private data_types */
875 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
876 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
877 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
878 for (DataTypeDefinition dataType : privateDataTypes) {
879 log.debug("Emitting private data type: component.name={} dataType.name={}",
880 component.getNormalizedName(), dataType.getName());
881 ToscaDataType toscaDataType = new ToscaDataType();
882 toscaDataType.setDerived_from(dataType.getDerivedFromName());
883 toscaDataType.setDescription(dataType.getDescription());
884 toscaDataType.setVersion(dataType.getVersion());
885 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
886 toscaDataType.setProperties(dataType.getProperties().stream()
887 .collect(Collectors.toMap(
888 PropertyDataDefinition::getName,
889 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
890 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
894 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
896 toscaNode.setData_types(toscaDataTypeMap);
899 // Extracted to method for code reuse
900 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
903 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
904 final ToscaProperty toscaProperty) {
905 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
906 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
907 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
910 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
911 final Map<String, DataTypeDefinition> dataTypes) {
912 if (CollectionUtils.isEmpty(attributeList)) {
913 return Collections.emptyMap();
915 final AttributeConverter converter = new AttributeConverter(dataTypes);
916 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
917 for (final AttributeDefinition attributeDefinition : attributeList) {
918 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
920 return toscaAttributeMap;
923 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
924 Component component, ToscaTemplate toscaNode,
925 Map<String, ToscaNodeType> nodeTypes,
926 ToscaNodeType toscaNodeType,
927 Map<String, DataTypeDefinition> dataTypes) {
928 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
930 if (capabilities.isRight()) {
931 return Either.right(capabilities.right().value());
933 toscaNodeType = capabilities.left().value();
934 log.debug("Capabilities converted for {}", component.getUniqueId());
936 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
937 .convertRequirements(componentsCache, component, toscaNodeType);
938 if (requirements.isRight()) {
939 return Either.right(requirements.right().value());
941 toscaNodeType = requirements.left().value();
942 log.debug("Requirements converted for {}", component.getUniqueId());
944 String toscaResourceName;
945 switch (component.getComponentType()) {
947 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
948 .getMetadataDataDefinition()).getToscaResourceName();
951 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
952 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
955 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
956 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
959 nodeTypes.put(toscaResourceName, toscaNodeType);
960 toscaNode.setNode_types(nodeTypes);
961 log.debug("finish convert node type for {}", component.getUniqueId());
962 return Either.left(toscaNode);
965 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
966 final Map<String, Component> componentCache,
967 final Map<String, DataTypeDefinition> dataTypes,
968 final ToscaTopolgyTemplate topologyTemplate) {
970 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
971 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
972 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
973 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
974 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
976 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
977 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
978 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
980 Map<String, ToscaGroupTemplate> groupsMap = null;
981 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
982 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
983 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
984 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
986 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
987 List<Object> occur = new ArrayList<>();
988 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
989 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
990 nodeTemplate.setOccurrences(occur);
992 if (componentInstance.getInstanceCount() != null) {
993 ObjectMapper objectMapper = new ObjectMapper();
994 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
996 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
997 nodeTemplate.setInstance_count(map);
1000 nodeTemplate.setType(componentInstance.getToscaComponentName());
1001 nodeTemplate.setDirectives(componentInstance.getDirectives());
1002 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1003 if (nodeFilter != null && nodeFilter.hasData()) {
1004 nodeTemplate.setNode_filter(nodeFilter);
1006 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1007 .getOriginComponent(componentCache, componentInstance);
1008 if (originComponentRes.isRight()) {
1009 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1012 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1013 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1014 if (requirements.isRight()) {
1015 convertNodeTemplatesRes = Either.right(requirements.right().value());
1018 final String instanceUniqueId = componentInstance.getUniqueId();
1019 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1021 nodeTemplate = requirements.left().value();
1023 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1025 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1026 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1027 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1029 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1032 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1033 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1034 if (capabilities.isRight()) {
1035 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1038 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1040 nodeTemplate = capabilities.left().value();
1041 final Map<String, Object> props = new HashMap<>();
1042 final Map<String, Object> attribs = new HashMap<>();
1044 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1045 // Adds the properties of parent component to map
1046 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1047 addAttributesOfParentComponent(originalComponent, attribs);
1050 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1051 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1053 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1054 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1057 if (componentInstancesInputs != null
1058 && componentInstancesInputs.containsKey(instanceUniqueId)
1059 && !isComponentOfTypeServiceProxy(componentInstance)) {
1060 //For service proxy the inputs are already handled under instance properties above
1061 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1064 //M3[00001] - NODE TEMPLATE INTERFACES - START
1065 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1066 //M3[00001] - NODE TEMPLATE INTERFACES - END
1067 if (MapUtils.isNotEmpty(props)) {
1068 nodeTemplate.setProperties(props);
1070 if (MapUtils.isNotEmpty(attribs)) {
1071 nodeTemplate.setAttributes(attribs);
1074 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1075 if (CollectionUtils.isNotEmpty(groupInstances)) {
1076 if (groupsMap == null) {
1077 groupsMap = new HashMap<>();
1079 for (final GroupInstance groupInst : groupInstances) {
1080 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1081 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1086 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1088 if (groupsMap != null) {
1089 log.debug("instance groups added");
1090 topologyTemplate.addGroups(groupsMap);
1092 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1093 ((Service) component).getForwardingPaths())) {
1094 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1095 ForwardingPathToscaUtil
1096 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1097 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1099 if (convertNodeTemplatesRes == null) {
1100 convertNodeTemplatesRes = Either.left(nodeTemplates);
1102 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1103 return convertNodeTemplatesRes;
1106 private Object convertToToscaObject(String value) {
1108 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1109 StringReader reader = new StringReader(value);
1110 JsonReader jsonReader = new JsonReader(reader);
1111 jsonReader.setLenient(true);
1112 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1113 if (jsonElement.isJsonObject()) {
1114 JsonObject jsonObj = jsonElement.getAsJsonObject();
1115 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1116 return mapConverterInst.handleComplexJsonValue(jsonElement);
1120 } catch (Exception e) {
1121 log.debug("convertToToscaValue failed to parse json value :", e);
1126 private Object parseToIntIfPossible(final String value) {
1127 final Integer intValue = Ints.tryParse(value);
1128 return intValue == null ? value : intValue;
1131 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1132 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1133 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1135 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1136 nodeTemplate.setInterfaces(null);
1140 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1142 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1143 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1145 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1146 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1148 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1149 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1152 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1153 return Objects.nonNull(componentInstance.getOriginType())
1154 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1157 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1158 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1159 String instanceUniqueId, Map<String, Object> props) {
1161 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1162 if (instanceInputsList != null) {
1163 instanceInputsList.forEach(input -> {
1164 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1165 : input.getDefaultValue();
1166 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1171 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1172 final Map<String, DataTypeDefinition> dataTypes,
1173 final String instanceUniqueId,
1174 final Map<String, Object> props) {
1176 if (isNotEmpty(componentInstancesProperties)) {
1177 componentInstancesProperties.get(instanceUniqueId)
1178 // Converts and adds each value to property map
1179 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1183 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1184 final String instanceUniqueId,
1185 final Map<String, Object> attribs) {
1187 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1188 componentInstancesAttributes.get(instanceUniqueId)
1189 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1193 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1194 Component componentOfInstance, Map<String, Object> props) {
1196 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1197 if (isNotEmpty(componentProperties)) {
1198 componentProperties.stream()
1199 // Filters out properties with empty default values
1200 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1201 // Converts and adds each value to property map
1202 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1206 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1208 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1209 if (isNotEmpty(componentAttributes)) {
1210 componentAttributes.stream()
1211 // Filters out Attributes with empty default values
1212 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1213 // Converts and adds each value to attribute map
1214 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1218 private ToscaNodeType createNodeType(Component component) {
1219 ToscaNodeType toscaNodeType = new ToscaNodeType();
1220 if (ModelConverter.isAtomicComponent(component)) {
1221 if (((Resource) component).getDerivedFrom() != null) {
1222 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1224 toscaNodeType.setDescription(component.getDescription());
1226 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1228 toscaNodeType.setDerived_from(derivedFrom);
1230 return toscaNodeType;
1233 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1235 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1236 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1237 List<ComponentInstance> componentInstances = container.getComponentInstances();
1238 if (CollectionUtils.isEmpty(componentInstances)) {
1241 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1242 componentInstances.stream()
1243 .filter(this::isComponentOfTypeServiceProxy)
1244 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1245 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1248 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1249 Component serviceComponent;
1250 ComponentParametersView componentParametersView = new ComponentParametersView();
1251 componentParametersView.disableAll();
1252 componentParametersView.setIgnoreInterfaces(false);
1253 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1254 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1255 if (service.isRight()) {
1256 log.debug("Failed to fetch original service component with id {} for instance {}",
1257 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1258 return Either.right(ToscaError.GENERAL_ERROR);
1260 serviceComponent = service.left().value();
1263 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1264 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1265 if (lifecycleTypeEither.isRight()) {
1266 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1267 return Either.right(ToscaError.GENERAL_ERROR);
1270 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1271 .map(InterfaceDataDefinition::getType)
1272 .collect(Collectors.toList());
1273 //Add interface types for local interfaces in the original service component for proxy
1274 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1275 allGlobalInterfaceTypes);
1276 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1277 proxyInterfaceTypes.putAll(localInterfaceTypes);
1281 return Either.left(proxyInterfaceTypes);
1284 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1285 Component container) {
1287 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1288 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1290 List<ComponentInstance> componentInstances = container.getComponentInstances();
1292 if (componentInstances == null || componentInstances.isEmpty()) {
1295 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1296 List<ComponentInstance> proxyInst = componentInstances.stream()
1297 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1298 .collect(Collectors.toList());
1299 if (proxyInst != null && !proxyInst.isEmpty()) {
1300 for (ComponentInstance inst : proxyInst) {
1301 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1305 if (serviceProxyInstanceList.isEmpty()) {
1308 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1309 .getLatestByName("serviceProxy", null);
1310 if (serviceProxyOrigin.isRight()) {
1311 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1312 serviceProxyOrigin.right().value());
1313 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1315 Component origComponent = serviceProxyOrigin.left().value();
1317 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1318 Component serviceComponent = null;
1319 ComponentParametersView componentParametersView = new ComponentParametersView();
1320 componentParametersView.disableAll();
1321 componentParametersView.setIgnoreCategories(false);
1322 componentParametersView.setIgnoreProperties(false);
1323 componentParametersView.setIgnoreInputs(false);
1324 componentParametersView.setIgnoreInterfaces(false);
1325 componentParametersView.setIgnoreRequirements(false);
1326 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1327 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1328 if (service.isRight()) {
1329 log.debug("Failed to fetch resource with id {} for instance {}",
1330 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1332 serviceComponent = service.left().value();
1335 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1336 entryProxy.getValue());
1337 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1340 return Either.left(nodeTypesMap);
1343 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1344 final Component container, final ToscaTemplate toscaNode) {
1345 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1347 if (CollectionUtils.isEmpty(componentInstances)) {
1350 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1351 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1352 .collect(Collectors.toList());
1353 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1354 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1355 final Map<String, ToscaNodeType> nodeTypes =
1356 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1357 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1363 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1364 Component proxyComponent, ComponentInstance componentInstance) {
1365 ToscaNodeType toscaNodeType = new ToscaNodeType();
1366 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1368 toscaNodeType.setDerived_from(derivedFrom);
1369 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1370 origComponent.getModel());
1371 if (dataTypesEither.isRight()) {
1372 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1374 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1375 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1376 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1378 if (MapUtils.isNotEmpty(capabilities)) {
1379 toscaNodeType.setCapabilities(capabilities);
1381 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1382 .convertProxyRequirements(componentCache, componentInstance);
1383 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1384 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1386 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1387 proxyProperties.ifPresent(toscaNodeType::setProperties);
1389 Map<String, Object> interfaceMap = new HashMap<>();
1390 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1391 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1392 if (proxyInterfaces.isPresent()) {
1393 interfaceMap = proxyInterfaces.get();
1396 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1399 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1400 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1402 return toscaNodeType;
1405 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1406 ComponentInstance componentInstance,
1407 List<RequirementCapabilityRelDef> relations,
1408 ToscaNodeTemplate nodeTypeTemplate,
1409 Component originComponent,
1410 Map<String, Component> componentCache) {
1412 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1414 if (isNotEmpty(requirementDefinitionList)) {
1416 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1417 requirementDefinitionList, originComponent, componentCache);
1418 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1419 nodeTypeTemplate.setRequirements(toscaRequirements);
1421 } catch (final Exception e) {
1422 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1423 componentInstance.getName(), e);
1424 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1427 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1428 return Either.left(nodeTypeTemplate);
1431 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1432 final ComponentInstance componentInstance,
1433 final List<RequirementCapabilityRelDef> filteredRelations,
1434 final Component originComponent,
1435 final Map<String, Component> componentCache)
1436 throws ToscaExportException {
1438 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1439 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1440 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1441 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1442 if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1443 toscaRequirements.add(toscaTemplateRequirementMap);
1447 return toscaRequirements;
1450 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1451 List<RequirementCapabilityRelDef> relations) {
1452 return relations.stream()
1453 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1456 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1457 final Component fromOriginComponent,
1458 final List<ComponentInstance> instancesList,
1459 final RequirementCapabilityRelDef relationshipDefinition,
1460 final Map<String, Component> componentCache)
1461 throws ToscaExportException {
1463 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1464 if (MapUtils.isEmpty(reqMap)) {
1465 return new HashMap<>();
1467 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1468 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1470 final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1471 .findFirst().orElse(null);
1472 if (toInstance == null) {
1473 final String errorMsg = String
1474 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1475 relationshipDefinition.getToNode());
1476 log.debug(errorMsg);
1477 throw new ToscaExportException(errorMsg);
1479 final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1480 if (reqOpt.isEmpty()) {
1481 final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1482 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1483 log.debug(errorMsg);
1484 throw new ToscaExportException(errorMsg);
1486 final ComponentParametersView filter = new ComponentParametersView(true);
1487 filter.setIgnoreComponentInstances(false);
1488 filter.setIgnoreCapabilities(false);
1489 filter.setIgnoreGroups(false);
1490 final Either<Component, StorageOperationStatus> getOriginRes =
1491 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1492 if (getOriginRes.isRight()) {
1493 final String errorMsg = String.format(
1494 "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1495 reqOpt.get().getName(), toInstance.getActualComponentUid());
1496 log.debug(errorMsg);
1497 throw new ToscaExportException(errorMsg);
1499 final Component toOriginComponent = getOriginRes.left().value();
1500 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1501 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1502 if (capOpt.isEmpty()) {
1503 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1504 if (capOpt.isEmpty()) {
1505 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1506 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1507 log.debug(errorMsg);
1508 throw new ToscaExportException(errorMsg);
1511 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1512 capabilityRequirementRelationship, toInstance, componentCache);
1515 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1516 CapabilityDefinition capability) {
1517 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1518 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1521 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1522 Component toOriginComponent, Component fromOriginComponent,
1523 RequirementDefinition requirement) {
1524 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1525 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1526 if (cap.isEmpty()) {
1527 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1528 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1533 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1534 final Component toOriginComponent,
1535 final CapabilityDefinition capability,
1536 final RequirementDefinition requirement,
1537 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1538 final ComponentInstance toInstance,
1539 final Map<String, Component> componentCache)
1540 throws ToscaExportException {
1542 List<String> reducedPath = capability.getPath();
1543 if (capability.getOwnerId() != null) {
1544 reducedPath = capabilityRequirementConverter
1545 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1547 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1548 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1549 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1550 if (capabilityNameEither.isRight()) {
1551 final String errorMsg = String.format(
1552 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1553 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1556 throw new ToscaExportException(errorMsg);
1558 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1559 .buildSubstitutedName(componentCache, fromOriginComponent,
1560 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1561 if (requirementNameEither.isRight()) {
1562 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1563 + "with name %s on a component with uniqueId %s",
1564 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1565 log.debug(errorMsg);
1566 throw new ToscaExportException(errorMsg);
1568 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1569 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1570 toscaRequirement.setNode(toInstance.getName());
1571 toscaRequirement.setCapability(capabilityNameEither.left().value());
1572 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1573 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1575 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1579 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1580 Map<String, List<RequirementDefinition>> reqMap,
1581 RelationshipInfo reqAndRelationshipPair,
1582 String fromInstanceId) {
1583 for (final List<RequirementDefinition> reqList : reqMap.values()) {
1584 final Optional<RequirementDefinition> reqOpt = reqList.stream()
1585 .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1586 if (reqOpt.isPresent()) {
1590 return Optional.empty();
1594 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1595 * 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
1596 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1598 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1599 RequirementDefinition requirement, String fromInstanceId) {
1600 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1603 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1604 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1605 reqAndRelationshipPair.getRequirement());
1608 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1612 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1613 Component originComponent) {
1614 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1615 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1616 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1619 private boolean isCvfc(Component component) {
1620 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1623 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1624 final Map<String, Component> componentCache) {
1625 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1626 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1627 if (toscaCapabilitiesRes.isRight()) {
1628 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1629 return Either.right(toscaCapabilitiesRes.right().value());
1631 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1632 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1633 return Either.left(toscaCapabilitiesRes.left().value());
1635 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1637 return Either.left(Collections.emptyMap());
1640 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1641 Map<String, DataTypeDefinition> dataTypes) {
1642 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1643 if (!toscaCapabilities.isEmpty()) {
1644 nodeType.setCapabilities(toscaCapabilities);
1646 log.debug("Finish convert Capabilities for node type");
1647 return Either.left(nodeType);
1650 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1651 if (artifacts == null) {
1654 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1655 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1656 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1657 artifact.setFile(entry.getValue().getFile());
1658 artifact.setType(entry.getValue().getType());
1659 artifact.setProperties(entry.getValue().getProperties());
1660 arts.put(entry.getKey(), artifact);
1665 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1666 if (inNodeFilter == null) {
1669 NodeFilter nodeFilter = new NodeFilter();
1670 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1671 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1672 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1673 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1674 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1675 nodeFilter.setCapabilities(capabilitiesCopy);
1677 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1678 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1679 nodeFilter.setProperties(propertiesCopy);
1681 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1682 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1686 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1687 if (substitutionFilterDataDefinition == null) {
1690 NodeFilter nodeFilter = new NodeFilter();
1691 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1692 if (!propertiesCopy.isEmpty()) {
1693 nodeFilter.setProperties(propertiesCopy);
1695 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1696 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1699 private Object cloneToscaId(Object toscaId) {
1700 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1703 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1704 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1705 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1708 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1709 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1710 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1714 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1715 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1716 final var capabilityFilter = new CapabilityFilter();
1717 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1718 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1719 capabilitiesCopy.add(capabilityFilterCopyMap);
1723 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1724 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1725 return Collections.emptyList();
1727 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1728 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1729 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1730 final String propertyName = propertyFilter.getName();
1731 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1732 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1733 if (constraints == null) {
1734 constraints = new ArrayList<>();
1736 constraints.add(buildNodeFilterValue(filterConstraint));
1741 propertyFilterDefinitionMap.entrySet().stream()
1742 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1743 .forEach(propertiesCopy::add);
1744 return propertiesCopy;
1747 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1748 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1750 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1751 return Collections.emptyList();
1753 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1754 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1755 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1756 final String propertyName = propertyFilter.getName();
1757 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1758 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1759 if (constraints == null) {
1760 constraints = new ArrayList<>();
1762 constraints.add(buildNodeFilterValue(filterConstraint));
1767 propertyFilterDefinitionMap.entrySet().stream()
1768 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1769 .forEach(propertiesCopy::add);
1770 return propertiesCopy;
1773 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1774 if (filterConstraint.getValue() instanceof ToscaFunction) {
1775 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1777 if (filterConstraint.getValue() instanceof List) {
1778 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1779 List<Object> toscaFunctionList = new ArrayList<>();
1780 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1781 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1782 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1785 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1786 ToscaType toscaType = ToscaType.getToscaType(
1787 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1788 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1789 } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1790 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1791 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1792 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1794 if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1795 filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1796 String.valueOf(filterConstraint.getValue())));
1798 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1801 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1802 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1803 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1806 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1809 private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1810 return ToscaType.BOOLEAN.getType().equals(propertyType);
1813 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1814 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1815 return Collections.emptyMap();
1817 Map<String, String[]> propertyMapping = new HashMap<>();
1818 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1819 Collectors.toList());
1821 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1822 propertyMappedInputList.forEach(inputDefinition -> {
1823 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1824 Optional<PropertyDefinition> property = component.getProperties().stream()
1825 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1826 if (property.isPresent()) {
1827 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1830 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1834 return propertyMapping;
1837 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1838 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1839 return Collections.emptyMap();
1841 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1842 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1845 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1846 if (Objects.isNull(proxyComponent)) {
1847 return Optional.empty();
1849 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1850 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1851 proxyProperties.putAll(proxyComponent.getProperties().stream()
1852 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1853 .toMap(PropertyDataDefinition::getName,
1854 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1856 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1859 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1860 String componentUniqueId) {
1861 if (CollectionUtils.isEmpty(componentInputs)) {
1862 return new HashMap<>();
1864 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1865 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1868 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1869 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1870 return Optional.empty();
1872 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1873 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1875 // always available in the proxy node template
1876 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1877 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1880 private Configuration getConfiguration() {
1881 return ConfigurationManager.getConfigurationManager().getConfiguration();
1884 private static class CustomRepresenter extends Representer {
1886 CustomRepresenter() {
1888 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1889 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1890 // null representer is exceptional and it is stored as an instance
1893 this.nullRepresenter = new RepresentNull();
1896 public boolean validateGetInputValue(final Object valueObj) {
1897 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1900 if (valueObj instanceof List) {
1901 return ((List) valueObj).size() > 1;
1906 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1907 if (valueObj instanceof List) {
1908 return ((List) valueObj).size() > 1;
1914 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1915 if (propertyValue == null) {
1918 // skip not relevant for Tosca property
1919 if ("dependencies".equals(property.getName())) {
1922 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1925 if (javaBean instanceof ToscaPropertyConstraint) {
1926 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1928 removeDefaultP(propertyValue);
1929 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1930 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1931 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1933 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1936 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1937 final Tag customTag) {
1938 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1939 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1940 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1943 private void removeDefaultP(final Object propertyValue) {
1944 if (propertyValue instanceof Map) {
1945 final Map mapPropertyValue = ((Map) propertyValue);
1946 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1947 Object defaultValue = null;
1948 while (iter.hasNext()) {
1949 final Map.Entry entry = iter.next();
1950 if ("_defaultp_".equals(entry.getKey())) {
1951 defaultValue = entry.getValue();
1953 } else if (entry.getValue() instanceof Map) {
1954 removeDefaultP(entry.getValue());
1957 if (defaultValue != null) {
1958 mapPropertyValue.putIfAbsent("default", defaultValue);
1964 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1965 // remove the bean type from the output yaml (!! ...)
1966 if (!classTags.containsKey(javaBean.getClass())) {
1967 addClassTag(javaBean.getClass(), Tag.MAP);
1969 return super.representJavaBean(properties, javaBean);
1972 private class RepresentToscaAttribute implements Represent {
1975 public Node representData(Object data) {
1976 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1977 return represent(toscaAttribute.asToscaMap());
1981 private class RepresentToscaPropertyAssignment implements Represent {
1983 public Node representData(Object data) {
1984 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1985 if (toscaOperationAssignment.getValue() instanceof String) {
1986 final String stringValue = (String) toscaOperationAssignment.getValue();
1987 if (isPropertyOrAttributeFunction(stringValue)) {
1988 return representGetAttribute(stringValue);
1990 return representScalar(Tag.STR, stringValue);
1992 return represent(null);
1995 public Node representGetAttribute(final String getAttributeFunction) {
1996 return represent(new Yaml().load(getAttributeFunction));
1999 public boolean isPropertyOrAttributeFunction(final String value) {
2001 final Yaml yaml = new Yaml();
2002 final Object yamlObj = yaml.load(value);
2003 if (!(yamlObj instanceof Map)) {
2006 final Map<String, Object> getAttributeMap = (Map) yamlObj;
2007 if (getAttributeMap.size() != 1) {
2010 final List<String> functionList = Arrays
2011 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2012 final Optional<String> function = getAttributeMap.keySet().stream()
2013 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2014 if (function.isEmpty()) {
2017 final String functionName = function.get();
2018 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2019 if (GET_INPUT.getFunctionName().equals(functionName)) {
2020 return validateGetInputValue(getAttributeValueObj);
2022 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2024 } catch (final Exception ignored) {
2030 private class RepresentNull implements Represent {
2033 public Node representData(Object data) {
2034 // possible values are here http://yaml.org/type/null.html
2035 return representScalar(Tag.NULL, "");
2040 private static class UnsortedPropertyUtils extends PropertyUtils {
2043 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2044 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2045 return new LinkedHashSet<>(fields);