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.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.google.common.primitives.Ints;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParser;
35 import com.google.gson.stream.JsonReader;
36 import fj.data.Either;
38 import java.io.StringReader;
39 import java.nio.file.Path;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedHashMap;
48 import java.util.LinkedHashSet;
49 import java.util.List;
51 import java.util.Map.Entry;
52 import java.util.Objects;
53 import java.util.Optional;
55 import java.util.function.Supplier;
56 import java.util.stream.Collectors;
58 import org.apache.commons.collections.CollectionUtils;
59 import org.apache.commons.collections.MapUtils;
60 import org.apache.commons.io.FilenameUtils;
61 import org.apache.commons.lang3.StringUtils;
62 import org.apache.commons.lang3.tuple.ImmutablePair;
63 import org.apache.commons.lang3.tuple.ImmutableTriple;
64 import org.apache.commons.lang3.tuple.Triple;
65 import org.onap.sdc.tosca.services.YamlUtil;
66 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
67 import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
68 import org.openecomp.sdc.be.config.Configuration;
69 import org.openecomp.sdc.be.config.ConfigurationManager;
70 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
71 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
72 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
84 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
85 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
86 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
87 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
88 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
89 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
90 import org.openecomp.sdc.be.exception.ToscaExportException;
91 import org.openecomp.sdc.be.model.ArtifactDefinition;
92 import org.openecomp.sdc.be.model.AttributeDefinition;
93 import org.openecomp.sdc.be.model.CapabilityDefinition;
94 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
95 import org.openecomp.sdc.be.model.Component;
96 import org.openecomp.sdc.be.model.ComponentInstance;
97 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
98 import org.openecomp.sdc.be.model.ComponentInstanceInput;
99 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
100 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
101 import org.openecomp.sdc.be.model.ComponentParametersView;
102 import org.openecomp.sdc.be.model.DataTypeDefinition;
103 import org.openecomp.sdc.be.model.GroupInstance;
104 import org.openecomp.sdc.be.model.InputDefinition;
105 import org.openecomp.sdc.be.model.InterfaceDefinition;
106 import org.openecomp.sdc.be.model.PropertyDefinition;
107 import org.openecomp.sdc.be.model.RelationshipInfo;
108 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
109 import org.openecomp.sdc.be.model.RequirementDefinition;
110 import org.openecomp.sdc.be.model.Resource;
111 import org.openecomp.sdc.be.model.Service;
112 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
113 import org.openecomp.sdc.be.model.category.CategoryDefinition;
114 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
115 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
116 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
117 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
118 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
119 import org.openecomp.sdc.be.model.tosca.ToscaType;
120 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
121 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
122 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
123 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
124 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
125 import org.openecomp.sdc.be.tosca.model.NodeFilter;
126 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
127 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
128 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
129 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
130 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
131 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
132 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
133 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
134 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
135 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
136 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
137 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
138 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
139 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
140 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
141 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
142 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
143 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
144 import org.openecomp.sdc.be.tosca.utils.InputConverter;
145 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
146 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
147 import org.openecomp.sdc.common.log.wrappers.Logger;
148 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
149 import org.springframework.beans.factory.annotation.Autowired;
150 import org.yaml.snakeyaml.DumperOptions;
151 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
152 import org.yaml.snakeyaml.Yaml;
153 import org.yaml.snakeyaml.introspector.BeanAccess;
154 import org.yaml.snakeyaml.introspector.Property;
155 import org.yaml.snakeyaml.introspector.PropertyUtils;
156 import org.yaml.snakeyaml.nodes.MappingNode;
157 import org.yaml.snakeyaml.nodes.Node;
158 import org.yaml.snakeyaml.nodes.NodeTuple;
159 import org.yaml.snakeyaml.nodes.Tag;
160 import org.yaml.snakeyaml.representer.Represent;
161 import org.yaml.snakeyaml.representer.Representer;
163 @org.springframework.stereotype.Component("tosca-export-handler")
164 public class ToscaExportHandler {
166 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
167 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
168 private static final String INVARIANT_UUID = "invariantUUID";
169 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
170 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
171 private static final String IMPORTS_FILE_KEY = "file";
172 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
173 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
174 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
175 private static final String NATIVE_ROOT = "tosca.nodes.Root";
176 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
177 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
178 private static final YamlUtil yamlUtil = new YamlUtil();
179 private final ApplicationDataTypeCache applicationDataTypeCache;
180 private final ToscaOperationFacade toscaOperationFacade;
181 private final CapabilityRequirementConverter capabilityRequirementConverter;
182 private final PolicyExportParser policyExportParser;
183 private final GroupExportParser groupExportParser;
184 private final PropertyConvertor propertyConvertor;
185 private final AttributeConverter attributeConverter;
186 private final InputConverter inputConverter;
187 private final OutputConverter outputConverter;
188 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
189 private final InterfacesOperationsConverter interfacesOperationsConverter;
190 private final ModelOperation modelOperation;
193 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
194 final ToscaOperationFacade toscaOperationFacade,
195 final CapabilityRequirementConverter capabilityRequirementConverter,
196 final PolicyExportParser policyExportParser,
197 final GroupExportParser groupExportParser,
198 final PropertyConvertor propertyConvertor,
199 final AttributeConverter attributeConverter,
200 final InputConverter inputConverter,
201 final OutputConverter outputConverter,
202 final InterfaceLifecycleOperation interfaceLifecycleOperation,
203 final InterfacesOperationsConverter interfacesOperationsConverter,
204 final ModelOperation modelOperation) {
205 this.applicationDataTypeCache = applicationDataTypeCache;
206 this.toscaOperationFacade = toscaOperationFacade;
207 this.capabilityRequirementConverter = capabilityRequirementConverter;
208 this.policyExportParser = policyExportParser;
209 this.groupExportParser = groupExportParser;
210 this.propertyConvertor = propertyConvertor;
211 this.attributeConverter = attributeConverter;
212 this.inputConverter = inputConverter;
213 this.outputConverter = outputConverter;
214 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
215 this.interfacesOperationsConverter = interfacesOperationsConverter;
216 this.modelOperation = modelOperation;
219 public static String getInterfaceFilename(String artifactName) {
220 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
223 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
224 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
227 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
228 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
231 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
232 return convertToToscaTemplate(component, false).left().map(this::createToscaRepresentation);
235 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component, Boolean isSkipImports) {
236 return convertToToscaTemplate(component, isSkipImports).left().map(this::createToscaRepresentation);
239 public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
240 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
243 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
244 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), false));
245 if (CollectionUtils.isEmpty(imports)) {
246 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
247 return Either.right(ToscaError.GENERAL_ERROR);
249 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
250 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
251 .startsWith("org.openecomp.resource.abstract.nodes.")) {
252 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
253 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
254 component.getModel());
255 if (baseType.isLeft() && baseType.left().value() != null) {
256 addDependencies(imports, dependencies, baseType.left().value(), false);
258 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
262 String toscaVersion = null;
263 if (component instanceof Resource) {
264 toscaVersion = ((Resource) component).getToscaVersion();
266 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
267 toscaTemplate.setImports(imports);
268 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
269 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
270 isAssociatedComponent);
271 if (toscaTemplateRes.isRight()) {
272 return Either.right(toscaTemplateRes.right().value());
274 toscaTemplate = toscaTemplateRes.left().value();
275 toscaTemplate.setDependencies(dependencies);
276 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
277 return Either.left(toscaRepresentation);
280 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
281 CustomRepresenter representer = new CustomRepresenter();
282 DumperOptions options = new DumperOptions();
283 options.setAllowReadOnlyProperties(false);
284 options.setPrettyFlow(true);
285 options.setDefaultFlowStyle(FlowStyle.FLOW);
286 options.setCanonical(false);
287 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
288 representer.setPropertyUtils(new UnsortedPropertyUtils());
290 Yaml yaml = new Yaml(representer, options);
291 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
292 String sb = getConfiguration().getHeatEnvArtifactHeader()
294 + getConfiguration().getHeatEnvArtifactFooter();
295 return ToscaRepresentation.make(sb.getBytes(), toscaTemplate);
298 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
299 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
300 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, false);
301 if (fillImports.isRight()) {
302 return Either.right(fillImports.right().value());
304 return Either.left(fillImports.left().value().left);
307 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component, final boolean isSkipImports) {
308 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
309 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
310 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
311 return Either.right(ToscaError.GENERAL_ERROR);
313 log.trace("start tosca export for {}", component.getUniqueId());
314 String toscaVersion = null;
315 if (component instanceof Resource) {
316 toscaVersion = ((Resource) component).getToscaVersion();
318 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
319 toscaTemplate.setMetadata(convertMetadata(component));
320 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
321 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
322 if (ModelConverter.isAtomicComponent(component)) {
323 log.trace("convert component as node type");
324 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
326 log.trace("convert component as topology template");
327 return convertToscaTemplate(component, toscaTemplate, isSkipImports);
331 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
332 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
333 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
336 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
337 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
338 if (dataTypesEither.isRight()) {
339 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
340 return Either.right(ToscaError.GENERAL_ERROR);
342 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
343 if (!dataTypeDefinition.isEmpty()) {
344 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
345 ToscaDataType toscaDataType = new ToscaDataType();
346 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
347 toscaDataType.setDescription(dataTypeDefinition.getDescription());
348 toscaDataType.setVersion(dataTypeDefinition.getVersion());
349 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
350 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
351 .collect(Collectors.toMap(
352 PropertyDataDefinition::getName,
353 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
354 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition,
355 toscaPropertyTobeValidated,
359 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
360 toscaTemplate.setData_types(toscaDataTypeMap);
362 return Either.left(toscaTemplate);
365 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId, final boolean isSkipImports) {
366 if (StringUtils.isEmpty(modelId)) {
367 return getDefaultToscaImportConfig();
370 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
371 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
372 final Set<Path> addedPathList = new HashSet<>();
373 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
374 var importPath = Path.of(toscaImportByModel.getFullPath());
375 if (!(isSkipImports && importPath.toString().equals(ADDITIONAL_TYPE_DEFINITIONS))) {
376 if (addedPathList.contains(importPath)) {
378 ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
380 final String fileName = FilenameUtils.getBaseName(importPath.toString());
381 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
382 addedPathList.add(importPath);
388 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode, boolean isSkipImports) {
389 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode, isSkipImports);
390 if (importsRes.isRight()) {
391 return Either.right(importsRes.right().value());
393 toscaNode = importsRes.left().value().left;
394 Map<String, Component> componentCache = importsRes.left().value().right;
395 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
396 if (nodeTypesMapEither.isRight()) {
397 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
398 return Either.right(nodeTypesMapEither.right().value());
400 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
401 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
402 toscaNode.setNode_types(nodeTypesMap);
404 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
405 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
406 if (proxyInterfaceTypesEither.isRight()) {
407 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
408 return Either.right(proxyInterfaceTypesEither.right().value());
410 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
411 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
412 toscaNode.setInterface_types(proxyInterfaceTypes);
414 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
415 if (dataTypesEither.isRight()) {
416 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
417 return Either.right(ToscaError.GENERAL_ERROR);
419 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
420 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
421 List<InputDefinition> inputDef = component.getInputs();
422 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
423 if (!inputs.isEmpty()) {
424 topologyTemplate.setInputs(inputs);
426 final Map<String, ToscaProperty> outputs;
428 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
429 } catch (final ToscaConversionException e) {
430 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
431 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
432 return Either.right(ToscaError.GENERAL_ERROR);
434 if (!outputs.isEmpty()) {
435 topologyTemplate.setOutputs(outputs);
437 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
438 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
439 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
440 if (nodeTemplates.isRight()) {
441 return Either.right(nodeTemplates.right().value());
443 log.debug("node templates converted");
444 topologyTemplate.setNode_templates(nodeTemplates.left().value());
446 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
447 .createFrom(topologyTemplate.getNode_templates());
448 if (!relationshipTemplatesMap.isEmpty()) {
449 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
451 addGroupsToTopologyTemplate(component, topologyTemplate);
453 addPoliciesToTopologyTemplate(component, topologyTemplate);
454 } catch (SdcResourceNotFoundException e) {
455 log.debug("Fail to add policies to topology template:", e);
456 return Either.right(ToscaError.GENERAL_ERROR);
459 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
460 } catch (final ToscaExportException e) {
461 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
462 return Either.right(e.getToscaError());
464 if (!topologyTemplate.isEmpty()) {
465 toscaNode.setTopology_template(topologyTemplate);
467 return Either.left(toscaNode);
470 private Either<String, ToscaError> createComponentToscaName(final Component component) {
471 switch (component.getComponentType()) {
473 final ResourceMetadataDataDefinition resourceMetadata =
474 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
475 return Either.left(resourceMetadata.getToscaResourceName());
477 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
479 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
480 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
484 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
485 final Map<String, Component> componentCache) throws ToscaExportException {
486 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
487 return Optional.empty();
490 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
491 if (toscaResourceNameEither.isRight()) {
492 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
494 final String toscaResourceName = toscaResourceNameEither.left().value();
496 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
497 if (doNotExtendBaseType(component)) {
498 substitutionMapping.setNode_type(component.getDerivedFromGenericType());
500 substitutionMapping.setNode_type(toscaResourceName);
502 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
504 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
505 if (capabilitiesEither.isRight()) {
506 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
508 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
509 if (!capabilityMap.isEmpty()) {
510 substitutionMapping.setCapabilities(capabilityMap);
512 final Either<Map<String, String[]>, ToscaError> requirements =
513 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
514 if (requirements.isRight()) {
515 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
517 final Map<String, String[]> requirementMap = requirements.left().value();
518 if (MapUtils.isNotEmpty(requirementMap)) {
519 substitutionMapping.setRequirements(requirementMap);
522 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
523 if (MapUtils.isNotEmpty(propertyMappingMap)) {
524 substitutionMapping.setProperties(propertyMappingMap);
527 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
528 if (MapUtils.isNotEmpty(attributesMappingMap)) {
529 substitutionMapping.setAttributes(attributesMappingMap);
532 return Optional.of(substitutionMapping);
535 private boolean doNotExtendBaseType(final Component component) {
536 final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig = ConfigurationManager.getConfigurationManager().getConfiguration()
537 .getServiceBaseNodeTypes();
538 List<CategoryDefinition> categories = component.getCategories();
539 if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
540 && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
541 return serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
546 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
547 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
548 return Optional.empty();
551 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
554 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
555 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
556 if (groups != null) {
557 topologyTemplate.addGroups(groups);
561 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
562 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
563 if (policies != null) {
564 topologyTemplate.addPolicies(policies);
568 private Map<String, Object> convertMetadata(Component component) {
569 return convertMetadata(component, false, null);
572 private Map<String, Object> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
573 Map<String, Object> toscaMetadata = new LinkedHashMap<>();
574 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
575 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
577 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
578 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
579 List<CategoryDefinition> categories = component.getCategories();
580 CategoryDefinition categoryDefinition = categories.get(0);
581 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
582 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
584 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
585 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
586 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
587 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
588 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
589 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
590 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
591 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
592 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
593 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
594 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
595 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
596 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
598 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
601 switch (component.getComponentType()) {
603 Resource resource = (Resource) component;
604 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
605 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
606 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
608 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
610 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
611 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
612 if (resource.getTenant() != null) {
613 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
615 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
616 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
617 toscaMetadata.put(resource.isTopologyTemplate() ? JsonPresentationFields.TEMPLATE_VERSION.getPresentation() : JsonPresentationFields.VERSION.getPresentation(), resource.getVersion());
620 Service service = (Service) component;
621 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
622 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
623 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
624 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
625 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
626 toscaMetadata.put(JsonPresentationFields.TEMPLATE_VERSION.getPresentation(), service.getVersion());
627 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
628 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
630 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
631 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
635 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
637 for (final String key : component.getCategorySpecificMetadata().keySet()) {
638 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
639 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
642 return toscaMetadata;
645 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
646 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
647 return INVARIANT_UUID;
649 return jsonPresentationField.getPresentation();
652 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate, boolean isSkipImports) {
653 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
654 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
655 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
656 return Either.right(ToscaError.GENERAL_ERROR);
658 Map<String, Component> componentCache = new HashMap<>();
659 if (!ModelConverter.isAtomicComponent(component)) {
660 final List<Map<String, Map<String, String>>> additionalImports =
661 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
662 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
663 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
664 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
665 if (!substituteTypeImportEntry.isEmpty()) {
666 additionalImports.add(substituteTypeImportEntry);
668 List<ComponentInstance> componentInstances = component.getComponentInstances();
669 if (componentInstances != null && !componentInstances.isEmpty()) {
670 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci, isSkipImports));
672 toscaTemplate.setDependencies(dependencies);
673 toscaTemplate.setImports(additionalImports);
675 log.debug("currently imports supported for VF and service only");
677 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
680 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
681 final Map<String, ArtifactDefinition> toscaArtifacts) {
682 if (doNotExtendBaseType(component)) {
683 return Collections.emptyMap();
685 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
686 return Collections.emptyMap();
688 if (MapUtils.isEmpty(toscaArtifacts)) {
689 return Collections.emptyMap();
691 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
692 if (artifactDefinition == null) {
693 return Collections.emptyMap();
695 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
696 return Map.of(importEntryName,
697 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
701 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
702 return getConfiguration().getDefaultImports();
705 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
706 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance,
707 final boolean isSkipImports) {
708 log.debug("createDependency componentCache {}", componentCache);
709 Component componentRI = componentCache.get(componentInstance.getComponentUid());
710 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
711 // all resource must be only once!
712 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
713 if ((resource.isRight()) && (log.isDebugEnabled())) {
714 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
715 componentInstance.getUniqueId());
718 final Component fetchedComponent = resource.left().value();
719 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
720 addDependencies(imports, dependencies, componentRI, isSkipImports);
725 * Sets a componentCache from the given component/resource.
727 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
728 final Component fetchedComponent) {
729 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
730 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
731 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
732 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
733 .getToscaFullElement(componentInstance.getSourceModelUid());
734 if (sourceService.isRight() && (log.isDebugEnabled())) {
735 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
736 componentInstance.getUniqueId());
738 final Component fetchedSource = sourceService.left().value();
739 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
740 return fetchedSource;
742 return fetchedComponent;
746 * Retrieves all derived_from nodes and stores it in a predictable order.
748 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
749 final Component fetchedComponent, final boolean isSkipImports) {
750 final Set<Component> componentsList = new LinkedHashSet<>();
751 if (fetchedComponent instanceof Resource) {
752 log.debug("fetchedComponent is a resource {}", fetchedComponent);
753 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
754 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
755 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
756 log.debug("Started entry.getValue() : {}", entry.getValue());
757 if (!NATIVE_ROOT.equals(entry.getValue())) {
758 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
759 if (resourcefetched != null && resourcefetched.isLeft()) {
760 componentsList.add(resourcefetched.left().value());
764 setImports(imports, dependencies, componentsList, isSkipImports);
766 setImports(imports, dependencies, fetchedComponent, isSkipImports);
772 * Returns all derived_from nodes found.
774 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
775 final Resource parentResource = (Resource) fetchedComponent;
776 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
777 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
778 componentsList.add(fetchedComponent);
779 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
780 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
781 .getToscaElement(componentInstance.getComponentUid());
782 if (resourcefetched != null && resourcefetched.isLeft()) {
783 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
784 if (MapUtils.isNotEmpty(derivedWithId)) {
785 derivedFromMapOfIdToName.putAll(derivedWithId);
790 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
792 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
793 return Optional.ofNullable(derivedFromMapOfIdToName);
797 * Creates a resource map and adds it to the import list.
799 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
800 final Set<Component> componentsList, boolean isSkipImports) {
801 componentsList.forEach(component -> setImports(imports, dependencies, component, isSkipImports));
804 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
805 final Component component, boolean isSkipImports) {
806 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
807 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
808 if (artifactDefinition != null) {
809 final Map<String, String> files = new HashMap<>();
810 final String artifactName = artifactDefinition.getArtifactName();
811 files.put(IMPORTS_FILE_KEY, artifactName);
812 final StringBuilder keyNameBuilder = new StringBuilder();
813 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
814 keyNameBuilder.append("-");
815 keyNameBuilder.append(component.getName());
816 if (!isSkipImports) {
817 addImports(imports, keyNameBuilder, files);
819 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
820 if (!ModelConverter.isAtomicComponent(component) && !isSkipImports) {
821 final Map<String, String> interfaceFiles = new HashMap<>();
822 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
823 keyNameBuilder.append("-interface");
824 addImports(imports, keyNameBuilder, interfaceFiles);
830 * Adds the found resource to the import definition list.
832 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
833 final Map<String, String> files) {
834 final String mapKey = keyNameBuilder.toString();
835 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
836 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
837 importsListMember.put(keyNameBuilder.toString(), files);
838 imports.add(importsListMember);
842 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
843 Map<String, ToscaNodeType> nodeTypes) {
844 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
847 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
848 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
849 boolean isAssociatedComponent) {
850 log.debug("start convert node type for {}", component.getUniqueId());
851 ToscaNodeType toscaNodeType = createNodeType(component);
852 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
853 .getAllInterfaceLifecycleTypes(component.getModel());
854 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
855 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
856 return Either.right(ToscaError.GENERAL_ERROR);
858 if (lifecycleTypeEither.isLeft()) {
859 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
860 .collect(Collectors.toList());
861 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
863 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
864 if (dataTypesEither.isRight()) {
865 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
866 return Either.right(ToscaError.GENERAL_ERROR);
868 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
869 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
870 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
871 if (!toscaAttributeMap.isEmpty()) {
872 toscaNodeType.setAttributes(toscaAttributeMap);
874 Map<String, ToscaProperty> convertedProperties = new HashMap();
875 if (CollectionUtils.isNotEmpty(component.getProperties())) {
876 List<PropertyDefinition> properties = component.getProperties();
877 convertedProperties = properties.stream()
878 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
879 .toMap(PropertyDataDefinition::getName,
880 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
882 if (MapUtils.isNotEmpty(convertedProperties)) {
883 toscaNodeType.setProperties(convertedProperties);
885 /* convert private data_types */
886 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
887 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
888 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
889 for (DataTypeDefinition dataType : privateDataTypes) {
890 log.debug("Emitting private data type: component.name={} dataType.name={}",
891 component.getNormalizedName(), dataType.getName());
892 ToscaDataType toscaDataType = new ToscaDataType();
893 toscaDataType.setDerived_from(dataType.getDerivedFromName());
894 toscaDataType.setDescription(dataType.getDescription());
895 toscaDataType.setVersion(dataType.getVersion());
896 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
897 toscaDataType.setProperties(dataType.getProperties().stream()
898 .collect(Collectors.toMap(
899 PropertyDataDefinition::getName,
900 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
901 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
905 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
907 toscaNode.setData_types(toscaDataTypeMap);
910 // Extracted to method for code reuse
911 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
914 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
915 final ToscaProperty toscaProperty) {
916 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
917 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
918 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
921 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
922 final Map<String, DataTypeDefinition> dataTypes) {
923 if (CollectionUtils.isEmpty(attributeList)) {
924 return Collections.emptyMap();
926 final AttributeConverter converter = new AttributeConverter(dataTypes);
927 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
928 for (final AttributeDefinition attributeDefinition : attributeList) {
929 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
931 return toscaAttributeMap;
934 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
935 Component component, ToscaTemplate toscaNode,
936 Map<String, ToscaNodeType> nodeTypes,
937 ToscaNodeType toscaNodeType,
938 Map<String, DataTypeDefinition> dataTypes) {
939 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
941 if (capabilities.isRight()) {
942 return Either.right(capabilities.right().value());
944 toscaNodeType = capabilities.left().value();
945 log.debug("Capabilities converted for {}", component.getUniqueId());
947 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
948 .convertRequirements(componentsCache, component, toscaNodeType);
949 if (requirements.isRight()) {
950 return Either.right(requirements.right().value());
952 toscaNodeType = requirements.left().value();
953 log.debug("Requirements converted for {}", component.getUniqueId());
955 String toscaResourceName;
956 switch (component.getComponentType()) {
958 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
959 .getMetadataDataDefinition()).getToscaResourceName();
962 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
963 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
966 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
967 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
970 nodeTypes.put(toscaResourceName, toscaNodeType);
971 toscaNode.setNode_types(nodeTypes);
972 log.debug("finish convert node type for {}", component.getUniqueId());
973 return Either.left(toscaNode);
976 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
977 final Map<String, Component> componentCache,
978 final Map<String, DataTypeDefinition> dataTypes,
979 final ToscaTopolgyTemplate topologyTemplate) {
981 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
982 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
983 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
984 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
985 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
987 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
988 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
989 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
991 Map<String, ToscaGroupTemplate> groupsMap = null;
992 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
993 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
994 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
995 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
997 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
998 List<Object> occur = new ArrayList<>();
999 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
1000 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
1001 nodeTemplate.setOccurrences(occur);
1003 if (componentInstance.getInstanceCount() != null) {
1004 ObjectMapper objectMapper = new ObjectMapper();
1005 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
1007 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
1008 nodeTemplate.setInstance_count(map);
1011 nodeTemplate.setType(componentInstance.getToscaComponentName());
1012 nodeTemplate.setDirectives(componentInstance.getDirectives());
1013 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1014 if (nodeFilter != null && nodeFilter.hasData()) {
1015 nodeTemplate.setNode_filter(nodeFilter);
1017 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1018 .getOriginComponent(componentCache, componentInstance);
1019 if (originComponentRes.isRight()) {
1020 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1023 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1024 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1025 if (requirements.isRight()) {
1026 convertNodeTemplatesRes = Either.right(requirements.right().value());
1029 final String instanceUniqueId = componentInstance.getUniqueId();
1030 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1032 nodeTemplate = requirements.left().value();
1034 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1036 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1037 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1038 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1040 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1043 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1044 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1045 if (capabilities.isRight()) {
1046 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1049 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1051 nodeTemplate = capabilities.left().value();
1052 final Map<String, Object> props = new HashMap<>();
1053 final Map<String, Object> attribs = new HashMap<>();
1055 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1056 // Adds the properties of parent component to map
1057 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1058 addAttributesOfParentComponent(originalComponent, attribs);
1061 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1062 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1064 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1065 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1068 if (componentInstancesInputs != null
1069 && componentInstancesInputs.containsKey(instanceUniqueId)
1070 && !isComponentOfTypeServiceProxy(componentInstance)) {
1071 //For service proxy the inputs are already handled under instance properties above
1072 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1075 //M3[00001] - NODE TEMPLATE INTERFACES - START
1076 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1077 //M3[00001] - NODE TEMPLATE INTERFACES - END
1078 if (MapUtils.isNotEmpty(props)) {
1079 nodeTemplate.setProperties(props);
1081 if (MapUtils.isNotEmpty(attribs)) {
1082 nodeTemplate.setAttributes(attribs);
1085 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1086 if (CollectionUtils.isNotEmpty(groupInstances)) {
1087 if (groupsMap == null) {
1088 groupsMap = new HashMap<>();
1090 for (final GroupInstance groupInst : groupInstances) {
1091 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1092 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1097 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1099 if (groupsMap != null) {
1100 log.debug("instance groups added");
1101 topologyTemplate.addGroups(groupsMap);
1103 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1104 ((Service) component).getForwardingPaths())) {
1105 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1106 ForwardingPathToscaUtil
1107 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1108 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1110 if (convertNodeTemplatesRes == null) {
1111 convertNodeTemplatesRes = Either.left(nodeTemplates);
1113 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1114 return convertNodeTemplatesRes;
1117 private Object convertToToscaObject(String value) {
1119 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1120 StringReader reader = new StringReader(value);
1121 JsonReader jsonReader = new JsonReader(reader);
1122 jsonReader.setLenient(true);
1123 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1124 if (jsonElement.isJsonObject()) {
1125 JsonObject jsonObj = jsonElement.getAsJsonObject();
1126 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1127 return mapConverterInst.handleComplexJsonValue(jsonElement);
1131 } catch (Exception e) {
1132 log.debug("convertToToscaValue failed to parse json value :", e);
1137 private Object parseToIntIfPossible(final String value) {
1138 final Integer intValue = Ints.tryParse(value);
1139 return intValue == null ? value : intValue;
1142 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1143 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1144 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1146 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1147 nodeTemplate.setInterfaces(null);
1151 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1153 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1154 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1156 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1157 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1159 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1160 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1163 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1164 return Objects.nonNull(componentInstance.getOriginType())
1165 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1168 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1169 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1170 String instanceUniqueId, Map<String, Object> props) {
1172 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1173 if (instanceInputsList != null) {
1174 instanceInputsList.forEach(input -> {
1175 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1176 : input.getDefaultValue();
1177 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1182 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1183 final Map<String, DataTypeDefinition> dataTypes,
1184 final String instanceUniqueId,
1185 final Map<String, Object> props) {
1187 if (isNotEmpty(componentInstancesProperties)) {
1188 componentInstancesProperties.get(instanceUniqueId)
1189 // Converts and adds each value to property map
1190 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1194 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1195 final String instanceUniqueId,
1196 final Map<String, Object> attribs) {
1198 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1199 componentInstancesAttributes.get(instanceUniqueId)
1200 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1204 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1205 Component componentOfInstance, Map<String, Object> props) {
1207 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1208 if (isNotEmpty(componentProperties)) {
1209 componentProperties.stream()
1210 // Filters out properties with empty default values
1211 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1212 // Converts and adds each value to property map
1213 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1217 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1219 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1220 if (isNotEmpty(componentAttributes)) {
1221 componentAttributes.stream()
1222 // Filters out Attributes with empty default values
1223 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1224 // Converts and adds each value to attribute map
1225 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1229 private ToscaNodeType createNodeType(Component component) {
1230 ToscaNodeType toscaNodeType = new ToscaNodeType();
1231 if (ModelConverter.isAtomicComponent(component)) {
1232 if (((Resource) component).getDerivedFrom() != null) {
1233 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1235 toscaNodeType.setDescription(component.getDescription());
1237 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1239 toscaNodeType.setDerived_from(derivedFrom);
1241 return toscaNodeType;
1244 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1246 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1247 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1248 List<ComponentInstance> componentInstances = container.getComponentInstances();
1249 if (CollectionUtils.isEmpty(componentInstances)) {
1252 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1253 componentInstances.stream()
1254 .filter(this::isComponentOfTypeServiceProxy)
1255 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1256 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1259 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1260 Component serviceComponent;
1261 ComponentParametersView componentParametersView = new ComponentParametersView();
1262 componentParametersView.disableAll();
1263 componentParametersView.setIgnoreInterfaces(false);
1264 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1265 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1266 if (service.isRight()) {
1267 log.debug("Failed to fetch original service component with id {} for instance {}",
1268 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1269 return Either.right(ToscaError.GENERAL_ERROR);
1271 serviceComponent = service.left().value();
1274 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1275 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1276 if (lifecycleTypeEither.isRight()) {
1277 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1278 return Either.right(ToscaError.GENERAL_ERROR);
1281 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1282 .map(InterfaceDataDefinition::getType)
1283 .collect(Collectors.toList());
1284 //Add interface types for local interfaces in the original service component for proxy
1285 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1286 allGlobalInterfaceTypes);
1287 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1288 proxyInterfaceTypes.putAll(localInterfaceTypes);
1292 return Either.left(proxyInterfaceTypes);
1295 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1296 Component container) {
1298 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1299 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1301 List<ComponentInstance> componentInstances = container.getComponentInstances();
1303 if (componentInstances == null || componentInstances.isEmpty()) {
1306 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1307 List<ComponentInstance> proxyInst = componentInstances.stream()
1308 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1309 .collect(Collectors.toList());
1310 if (proxyInst != null && !proxyInst.isEmpty()) {
1311 for (ComponentInstance inst : proxyInst) {
1312 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1316 if (serviceProxyInstanceList.isEmpty()) {
1319 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1320 .getLatestByName("serviceProxy", null);
1321 if (serviceProxyOrigin.isRight()) {
1322 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1323 serviceProxyOrigin.right().value());
1324 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1326 Component origComponent = serviceProxyOrigin.left().value();
1328 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1329 Component serviceComponent = null;
1330 ComponentParametersView componentParametersView = new ComponentParametersView();
1331 componentParametersView.disableAll();
1332 componentParametersView.setIgnoreCategories(false);
1333 componentParametersView.setIgnoreProperties(false);
1334 componentParametersView.setIgnoreInputs(false);
1335 componentParametersView.setIgnoreInterfaces(false);
1336 componentParametersView.setIgnoreRequirements(false);
1337 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1338 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1339 if (service.isRight()) {
1340 log.debug("Failed to fetch resource with id {} for instance {}",
1341 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1343 serviceComponent = service.left().value();
1346 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1347 entryProxy.getValue());
1348 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1351 return Either.left(nodeTypesMap);
1354 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1355 final Component container, final ToscaTemplate toscaNode) {
1356 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1358 if (CollectionUtils.isEmpty(componentInstances)) {
1361 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1362 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1363 .collect(Collectors.toList());
1364 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1365 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1366 final Map<String, ToscaNodeType> nodeTypes =
1367 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1368 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1374 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1375 Component proxyComponent, ComponentInstance componentInstance) {
1376 ToscaNodeType toscaNodeType = new ToscaNodeType();
1377 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1379 toscaNodeType.setDerived_from(derivedFrom);
1380 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1381 origComponent.getModel());
1382 if (dataTypesEither.isRight()) {
1383 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1385 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1386 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1387 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1389 if (MapUtils.isNotEmpty(capabilities)) {
1390 toscaNodeType.setCapabilities(capabilities);
1392 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1393 .convertProxyRequirements(componentCache, componentInstance);
1394 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1395 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1397 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1398 proxyProperties.ifPresent(toscaNodeType::setProperties);
1400 Map<String, Object> interfaceMap = new HashMap<>();
1401 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1402 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1403 if (proxyInterfaces.isPresent()) {
1404 interfaceMap = proxyInterfaces.get();
1407 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1410 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1411 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1413 return toscaNodeType;
1416 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1417 ComponentInstance componentInstance,
1418 List<RequirementCapabilityRelDef> relations,
1419 ToscaNodeTemplate nodeTypeTemplate,
1420 Component originComponent,
1421 Map<String, Component> componentCache) {
1423 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1425 if (isNotEmpty(requirementDefinitionList)) {
1427 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1428 requirementDefinitionList, originComponent, componentCache);
1429 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1430 nodeTypeTemplate.setRequirements(toscaRequirements);
1432 } catch (final Exception e) {
1433 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1434 componentInstance.getName(), e);
1435 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1438 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1439 return Either.left(nodeTypeTemplate);
1442 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1443 final ComponentInstance componentInstance,
1444 final List<RequirementCapabilityRelDef> filteredRelations,
1445 final Component originComponent,
1446 final Map<String, Component> componentCache)
1447 throws ToscaExportException {
1449 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1450 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1451 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1452 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1453 if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1454 toscaRequirements.add(toscaTemplateRequirementMap);
1458 return toscaRequirements;
1461 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1462 List<RequirementCapabilityRelDef> relations) {
1463 return relations.stream()
1464 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1467 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1468 final Component fromOriginComponent,
1469 final List<ComponentInstance> instancesList,
1470 final RequirementCapabilityRelDef relationshipDefinition,
1471 final Map<String, Component> componentCache)
1472 throws ToscaExportException {
1474 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1475 if (MapUtils.isEmpty(reqMap)) {
1476 return new HashMap<>();
1478 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1479 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1481 final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1482 .findFirst().orElse(null);
1483 if (toInstance == null) {
1484 final String errorMsg = String
1485 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1486 relationshipDefinition.getToNode());
1487 log.debug(errorMsg);
1488 throw new ToscaExportException(errorMsg);
1490 final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1491 if (reqOpt.isEmpty()) {
1492 final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1493 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1494 log.debug(errorMsg);
1495 throw new ToscaExportException(errorMsg);
1497 final ComponentParametersView filter = new ComponentParametersView(true);
1498 filter.setIgnoreComponentInstances(false);
1499 filter.setIgnoreCapabilities(false);
1500 filter.setIgnoreGroups(false);
1501 final Either<Component, StorageOperationStatus> getOriginRes =
1502 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1503 if (getOriginRes.isRight()) {
1504 final String errorMsg = String.format(
1505 "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1506 reqOpt.get().getName(), toInstance.getActualComponentUid());
1507 log.debug(errorMsg);
1508 throw new ToscaExportException(errorMsg);
1510 final Component toOriginComponent = getOriginRes.left().value();
1511 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1512 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1513 if (capOpt.isEmpty()) {
1514 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1515 if (capOpt.isEmpty()) {
1516 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1517 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1518 log.debug(errorMsg);
1519 throw new ToscaExportException(errorMsg);
1522 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1523 capabilityRequirementRelationship, toInstance, componentCache);
1526 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1527 CapabilityDefinition capability) {
1528 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1529 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1532 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1533 Component toOriginComponent, Component fromOriginComponent,
1534 RequirementDefinition requirement) {
1535 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1536 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1537 if (cap.isEmpty()) {
1538 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1539 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1544 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1545 final Component toOriginComponent,
1546 final CapabilityDefinition capability,
1547 final RequirementDefinition requirement,
1548 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1549 final ComponentInstance toInstance,
1550 final Map<String, Component> componentCache)
1551 throws ToscaExportException {
1553 List<String> reducedPath = capability.getPath();
1554 if (capability.getOwnerId() != null) {
1555 reducedPath = capabilityRequirementConverter
1556 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1558 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1559 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1560 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1561 if (capabilityNameEither.isRight()) {
1562 final String errorMsg = String.format(
1563 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1564 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1567 throw new ToscaExportException(errorMsg);
1569 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1570 .buildSubstitutedName(componentCache, fromOriginComponent,
1571 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1572 if (requirementNameEither.isRight()) {
1573 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1574 + "with name %s on a component with uniqueId %s",
1575 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1576 log.debug(errorMsg);
1577 throw new ToscaExportException(errorMsg);
1579 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1580 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1581 toscaRequirement.setNode(toInstance.getName());
1582 toscaRequirement.setCapability(capabilityNameEither.left().value());
1583 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1584 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1586 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1590 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1591 Map<String, List<RequirementDefinition>> reqMap,
1592 RelationshipInfo reqAndRelationshipPair,
1593 String fromInstanceId) {
1594 for (final List<RequirementDefinition> reqList : reqMap.values()) {
1595 final Optional<RequirementDefinition> reqOpt = reqList.stream()
1596 .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1597 if (reqOpt.isPresent()) {
1601 return Optional.empty();
1605 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1606 * 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
1607 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1609 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1610 RequirementDefinition requirement, String fromInstanceId) {
1611 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1614 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1615 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1616 reqAndRelationshipPair.getRequirement());
1619 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1623 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1624 Component originComponent) {
1625 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1626 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1627 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1630 private boolean isCvfc(Component component) {
1631 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1634 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1635 final Map<String, Component> componentCache) {
1636 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1637 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1638 if (toscaCapabilitiesRes.isRight()) {
1639 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1640 return Either.right(toscaCapabilitiesRes.right().value());
1642 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1643 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1644 return Either.left(toscaCapabilitiesRes.left().value());
1646 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1648 return Either.left(Collections.emptyMap());
1651 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1652 Map<String, DataTypeDefinition> dataTypes) {
1653 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1654 if (!toscaCapabilities.isEmpty()) {
1655 nodeType.setCapabilities(toscaCapabilities);
1657 log.debug("Finish convert Capabilities for node type");
1658 return Either.left(nodeType);
1661 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1662 if (artifacts == null) {
1665 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1666 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1667 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1668 artifact.setFile(entry.getValue().getFile());
1669 artifact.setType(entry.getValue().getType());
1670 artifact.setProperties(entry.getValue().getProperties());
1671 arts.put(entry.getKey(), artifact);
1676 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1677 if (inNodeFilter == null) {
1680 NodeFilter nodeFilter = new NodeFilter();
1681 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1682 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1683 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1684 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1685 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1686 nodeFilter.setCapabilities(capabilitiesCopy);
1688 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1689 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1690 nodeFilter.setProperties(propertiesCopy);
1692 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1693 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1696 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1697 if (substitutionFilterDataDefinition == null) {
1700 NodeFilter nodeFilter = new NodeFilter();
1701 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1702 if (!propertiesCopy.isEmpty()) {
1703 nodeFilter.setProperties(propertiesCopy);
1705 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1706 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1709 private Object cloneToscaId(Object toscaId) {
1710 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1713 private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
1714 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1715 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1718 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1719 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1720 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1724 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1725 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1726 final var capabilityFilter = new CapabilityFilter();
1727 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1728 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1729 capabilitiesCopy.add(capabilityFilterCopyMap);
1733 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1734 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1735 return Collections.emptyList();
1737 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1738 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1739 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1740 final String propertyName = propertyFilter.getName();
1741 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1742 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1743 if (constraints == null) {
1744 constraints = new ArrayList<>();
1746 constraints.add(buildNodeFilterValue(filterConstraint));
1751 propertyFilterDefinitionMap.entrySet().stream()
1752 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1753 .forEach(propertiesCopy::add);
1754 return propertiesCopy;
1757 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1758 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1760 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1761 return Collections.emptyList();
1763 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1764 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1765 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1766 final String propertyName = propertyFilter.getName();
1767 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1768 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1769 if (constraints == null) {
1770 constraints = new ArrayList<>();
1772 constraints.add(buildNodeFilterValue(filterConstraint));
1777 propertyFilterDefinitionMap.entrySet().stream()
1778 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1779 .forEach(propertiesCopy::add);
1780 return propertiesCopy;
1783 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1784 if (filterConstraint.getValue() instanceof ToscaFunction) {
1785 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1787 if (filterConstraint.getValue() instanceof List) {
1788 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1789 List<Object> toscaFunctionList = new ArrayList<>();
1790 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1791 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1792 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1795 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1796 ToscaType toscaType = ToscaType.getToscaType(
1797 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1798 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1799 } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1800 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1801 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1802 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1804 if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1805 filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1806 String.valueOf(filterConstraint.getValue())));
1808 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1811 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1812 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1813 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1816 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1819 private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1820 return ToscaType.BOOLEAN.getType().equals(propertyType);
1823 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1824 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1825 return Collections.emptyMap();
1827 Map<String, String[]> propertyMapping = new HashMap<>();
1828 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1829 Collectors.toList());
1831 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1832 propertyMappedInputList.forEach(inputDefinition -> {
1833 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1834 Optional<PropertyDefinition> property = component.getProperties().stream()
1835 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1836 if (property.isPresent()) {
1837 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1840 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1844 return propertyMapping;
1847 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1848 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1849 return Collections.emptyMap();
1851 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1852 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1855 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1856 if (Objects.isNull(proxyComponent)) {
1857 return Optional.empty();
1859 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1860 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1861 proxyProperties.putAll(proxyComponent.getProperties().stream()
1862 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1863 .toMap(PropertyDataDefinition::getName,
1864 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1866 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1869 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1870 String componentUniqueId) {
1871 if (CollectionUtils.isEmpty(componentInputs)) {
1872 return new HashMap<>();
1874 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1875 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1878 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1879 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1880 return Optional.empty();
1882 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1883 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1885 // always available in the proxy node template
1886 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1887 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1890 private Configuration getConfiguration() {
1891 return ConfigurationManager.getConfigurationManager().getConfiguration();
1894 private static class CustomRepresenter extends Representer {
1896 CustomRepresenter() {
1897 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1898 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1899 // null representer is exceptional and it is stored as an instance
1902 this.nullRepresenter = new RepresentNull();
1905 public boolean validateGetInputValue(final Object valueObj) {
1906 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1909 if (valueObj instanceof List) {
1910 return ((List) valueObj).size() > 1;
1915 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1916 if (valueObj instanceof List) {
1917 return ((List) valueObj).size() > 1;
1923 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1924 if (propertyValue == null) {
1927 // skip not relevant for Tosca property
1928 if ("dependencies".equals(property.getName())) {
1931 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1934 if (javaBean instanceof ToscaPropertyConstraint) {
1935 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1937 removeDefaultP(propertyValue);
1938 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1939 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1940 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1942 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1945 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1946 final Tag customTag) {
1947 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1948 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1949 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1952 private void removeDefaultP(final Object propertyValue) {
1953 if (propertyValue instanceof Map) {
1954 final Map mapPropertyValue = ((Map) propertyValue);
1955 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1956 Object defaultValue = null;
1957 while (iter.hasNext()) {
1958 final Map.Entry entry = iter.next();
1959 if ("_defaultp_".equals(entry.getKey())) {
1960 defaultValue = entry.getValue();
1962 } else if (entry.getValue() instanceof Map) {
1963 removeDefaultP(entry.getValue());
1966 if (defaultValue != null) {
1967 mapPropertyValue.putIfAbsent("default", defaultValue);
1973 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1974 // remove the bean type from the output yaml (!! ...)
1975 if (!classTags.containsKey(javaBean.getClass())) {
1976 addClassTag(javaBean.getClass(), Tag.MAP);
1978 return super.representJavaBean(properties, javaBean);
1981 private class RepresentToscaAttribute implements Represent {
1984 public Node representData(Object data) {
1985 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1986 return represent(toscaAttribute.asToscaMap());
1990 private class RepresentToscaPropertyAssignment implements Represent {
1992 public Node representData(Object data) {
1993 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1994 if (toscaOperationAssignment.getValue() instanceof String) {
1995 final String stringValue = (String) toscaOperationAssignment.getValue();
1996 if (isPropertyOrAttributeFunction(stringValue)) {
1997 return representGetAttribute(stringValue);
1999 return representScalar(Tag.STR, stringValue);
2001 return represent(null);
2004 public Node representGetAttribute(final String getAttributeFunction) {
2005 return represent(new Yaml().load(getAttributeFunction));
2008 public boolean isPropertyOrAttributeFunction(final String value) {
2010 final Yaml yaml = new Yaml();
2011 final Object yamlObj = yaml.load(value);
2012 if (!(yamlObj instanceof Map)) {
2015 final Map<String, Object> getAttributeMap = (Map) yamlObj;
2016 if (getAttributeMap.size() != 1) {
2019 final List<String> functionList = Arrays
2020 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2021 final Optional<String> function = getAttributeMap.keySet().stream()
2022 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2023 if (function.isEmpty()) {
2026 final String functionName = function.get();
2027 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2028 if (GET_INPUT.getFunctionName().equals(functionName)) {
2029 return validateGetInputValue(getAttributeValueObj);
2031 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2033 } catch (final Exception ignored) {
2039 private class RepresentNull implements Represent {
2042 public Node representData(Object data) {
2043 // possible values are here http://yaml.org/type/null.html
2044 return representScalar(Tag.NULL, "");
2049 private static class UnsortedPropertyUtils extends PropertyUtils {
2052 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2053 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2054 return new LinkedHashSet<>(fields);