2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.tosca;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.collections.MapUtils.isNotEmpty;
24 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
25 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
29 import com.fasterxml.jackson.databind.ObjectMapper;
30 import com.google.common.primitives.Ints;
31 import com.google.gson.JsonElement;
32 import com.google.gson.JsonObject;
33 import com.google.gson.JsonParser;
34 import com.google.gson.stream.JsonReader;
35 import fj.data.Either;
37 import java.io.StringReader;
38 import java.nio.file.Path;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedHashMap;
47 import java.util.LinkedHashSet;
48 import java.util.List;
50 import java.util.Map.Entry;
51 import java.util.Objects;
52 import java.util.Optional;
54 import java.util.function.Supplier;
55 import java.util.stream.Collectors;
57 import org.apache.commons.collections.CollectionUtils;
58 import org.apache.commons.collections.MapUtils;
59 import org.apache.commons.io.FilenameUtils;
60 import org.apache.commons.lang3.StringUtils;
61 import org.apache.commons.lang3.tuple.ImmutablePair;
62 import org.apache.commons.lang3.tuple.ImmutableTriple;
63 import org.apache.commons.lang3.tuple.Triple;
64 import org.onap.sdc.tosca.services.YamlUtil;
65 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
66 import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
67 import org.openecomp.sdc.be.config.Configuration;
68 import org.openecomp.sdc.be.config.ConfigurationManager;
69 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
70 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
71 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
84 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
85 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
86 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
87 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
88 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
89 import org.openecomp.sdc.be.exception.ToscaExportException;
90 import org.openecomp.sdc.be.model.ArtifactDefinition;
91 import org.openecomp.sdc.be.model.AttributeDefinition;
92 import org.openecomp.sdc.be.model.CapabilityDefinition;
93 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
94 import org.openecomp.sdc.be.model.Component;
95 import org.openecomp.sdc.be.model.ComponentInstance;
96 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
97 import org.openecomp.sdc.be.model.ComponentInstanceInput;
98 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
99 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
100 import org.openecomp.sdc.be.model.ComponentParametersView;
101 import org.openecomp.sdc.be.model.DataTypeDefinition;
102 import org.openecomp.sdc.be.model.GroupInstance;
103 import org.openecomp.sdc.be.model.InputDefinition;
104 import org.openecomp.sdc.be.model.InterfaceDefinition;
105 import org.openecomp.sdc.be.model.PropertyDefinition;
106 import org.openecomp.sdc.be.model.RelationshipInfo;
107 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
108 import org.openecomp.sdc.be.model.RequirementDefinition;
109 import org.openecomp.sdc.be.model.Resource;
110 import org.openecomp.sdc.be.model.Service;
111 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
112 import org.openecomp.sdc.be.model.category.CategoryDefinition;
113 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
114 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
115 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
116 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
117 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
118 import org.openecomp.sdc.be.model.tosca.ToscaType;
119 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
120 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
121 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
122 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
123 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
124 import org.openecomp.sdc.be.tosca.model.NodeFilter;
125 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
126 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
127 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
128 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
129 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
130 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
131 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
132 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
133 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
134 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
135 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
136 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
137 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
138 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
139 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
140 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
141 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
142 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
143 import org.openecomp.sdc.be.tosca.utils.InputConverter;
144 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
145 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
146 import org.openecomp.sdc.common.log.wrappers.Logger;
147 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
148 import org.springframework.beans.factory.annotation.Autowired;
149 import org.yaml.snakeyaml.DumperOptions;
150 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
151 import org.yaml.snakeyaml.Yaml;
152 import org.yaml.snakeyaml.introspector.BeanAccess;
153 import org.yaml.snakeyaml.introspector.Property;
154 import org.yaml.snakeyaml.introspector.PropertyUtils;
155 import org.yaml.snakeyaml.nodes.MappingNode;
156 import org.yaml.snakeyaml.nodes.Node;
157 import org.yaml.snakeyaml.nodes.NodeTuple;
158 import org.yaml.snakeyaml.nodes.Tag;
159 import org.yaml.snakeyaml.representer.Represent;
160 import org.yaml.snakeyaml.representer.Representer;
162 @org.springframework.stereotype.Component("tosca-export-handler")
163 public class ToscaExportHandler {
165 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
166 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
167 private static final String INVARIANT_UUID = "invariantUUID";
168 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
169 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
170 private static final String IMPORTS_FILE_KEY = "file";
171 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
172 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
173 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
174 private static final String NATIVE_ROOT = "tosca.nodes.Root";
175 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
176 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
177 private static final YamlUtil yamlUtil = new YamlUtil();
178 private final ApplicationDataTypeCache applicationDataTypeCache;
179 private final ToscaOperationFacade toscaOperationFacade;
180 private final CapabilityRequirementConverter capabilityRequirementConverter;
181 private final PolicyExportParser policyExportParser;
182 private final GroupExportParser groupExportParser;
183 private final PropertyConvertor propertyConvertor;
184 private final AttributeConverter attributeConverter;
185 private final InputConverter inputConverter;
186 private final OutputConverter outputConverter;
187 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
188 private final InterfacesOperationsConverter interfacesOperationsConverter;
189 private final ModelOperation modelOperation;
192 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
193 final ToscaOperationFacade toscaOperationFacade,
194 final CapabilityRequirementConverter capabilityRequirementConverter,
195 final PolicyExportParser policyExportParser,
196 final GroupExportParser groupExportParser,
197 final PropertyConvertor propertyConvertor,
198 final AttributeConverter attributeConverter,
199 final InputConverter inputConverter,
200 final OutputConverter outputConverter,
201 final InterfaceLifecycleOperation interfaceLifecycleOperation,
202 final InterfacesOperationsConverter interfacesOperationsConverter,
203 final ModelOperation modelOperation) {
204 this.applicationDataTypeCache = applicationDataTypeCache;
205 this.toscaOperationFacade = toscaOperationFacade;
206 this.capabilityRequirementConverter = capabilityRequirementConverter;
207 this.policyExportParser = policyExportParser;
208 this.groupExportParser = groupExportParser;
209 this.propertyConvertor = propertyConvertor;
210 this.attributeConverter = attributeConverter;
211 this.inputConverter = inputConverter;
212 this.outputConverter = outputConverter;
213 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
214 this.interfacesOperationsConverter = interfacesOperationsConverter;
215 this.modelOperation = modelOperation;
218 public static String getInterfaceFilename(String artifactName) {
219 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
222 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
223 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
226 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
227 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
230 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
231 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
234 public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
235 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
238 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
239 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
240 if (CollectionUtils.isEmpty(imports)) {
241 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
242 return Either.right(ToscaError.GENERAL_ERROR);
244 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
245 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
246 .startsWith("org.openecomp.resource.abstract.nodes.")) {
247 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
248 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
249 component.getModel());
250 if (baseType.isLeft() && baseType.left().value() != null) {
251 addDependencies(imports, dependencies, baseType.left().value());
253 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
257 String toscaVersion = null;
258 if (component instanceof Resource) {
259 toscaVersion = ((Resource) component).getToscaVersion();
261 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
262 toscaTemplate.setImports(imports);
263 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
264 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
265 isAssociatedComponent);
266 if (toscaTemplateRes.isRight()) {
267 return Either.right(toscaTemplateRes.right().value());
269 toscaTemplate = toscaTemplateRes.left().value();
270 toscaTemplate.setDependencies(dependencies);
271 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
272 return Either.left(toscaRepresentation);
275 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
276 CustomRepresenter representer = new CustomRepresenter();
277 DumperOptions options = new DumperOptions();
278 options.setAllowReadOnlyProperties(false);
279 options.setPrettyFlow(true);
280 options.setDefaultFlowStyle(FlowStyle.FLOW);
281 options.setCanonical(false);
282 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
283 representer.setPropertyUtils(new UnsortedPropertyUtils());
286 Yaml yaml = new Yaml(representer, options);
287 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
288 String sb = getConfiguration().getHeatEnvArtifactHeader()
290 + getConfiguration().getHeatEnvArtifactFooter();
291 return ToscaRepresentation.make(sb.getBytes(), toscaTemplate);
294 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
295 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
296 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
297 if (fillImports.isRight()) {
298 return Either.right(fillImports.right().value());
300 return Either.left(fillImports.left().value().left);
303 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
304 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
305 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
306 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
307 return Either.right(ToscaError.GENERAL_ERROR);
309 log.trace("start tosca export for {}", component.getUniqueId());
310 String toscaVersion = null;
311 if (component instanceof Resource) {
312 toscaVersion = ((Resource) component).getToscaVersion();
314 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
315 toscaTemplate.setMetadata(convertMetadata(component));
316 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
317 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
318 if (ModelConverter.isAtomicComponent(component)) {
319 log.trace("convert component as node type");
320 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
322 log.trace("convert component as topology template");
323 return convertToscaTemplate(component, toscaTemplate);
327 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
328 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
329 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
332 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
333 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
334 if (dataTypesEither.isRight()) {
335 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
336 return Either.right(ToscaError.GENERAL_ERROR);
338 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
339 if (!dataTypeDefinition.isEmpty()) {
340 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
341 ToscaDataType toscaDataType = new ToscaDataType();
342 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
343 toscaDataType.setDescription(dataTypeDefinition.getDescription());
344 toscaDataType.setVersion(dataTypeDefinition.getVersion());
345 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
346 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
347 .collect(Collectors.toMap(
348 PropertyDataDefinition::getName,
349 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
350 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition, toscaPropertyTobeValidated,
354 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
355 toscaTemplate.setData_types(toscaDataTypeMap);
357 return Either.left(toscaTemplate);
360 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
361 if (modelId == null) {
362 return getDefaultToscaImportConfig();
365 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
366 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
367 final Set<Path> addedPathList = new HashSet<>();
368 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
369 var importPath = Path.of(toscaImportByModel.getFullPath());
370 if (addedPathList.contains(importPath)) {
371 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
373 final String fileName = FilenameUtils.getBaseName(importPath.toString());
374 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
375 addedPathList.add(importPath);
380 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
381 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
382 if (importsRes.isRight()) {
383 return Either.right(importsRes.right().value());
385 toscaNode = importsRes.left().value().left;
386 Map<String, Component> componentCache = importsRes.left().value().right;
387 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
388 if (nodeTypesMapEither.isRight()) {
389 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
390 return Either.right(nodeTypesMapEither.right().value());
392 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
393 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
394 toscaNode.setNode_types(nodeTypesMap);
396 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
397 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
398 if (proxyInterfaceTypesEither.isRight()) {
399 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
400 return Either.right(proxyInterfaceTypesEither.right().value());
402 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
403 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
404 toscaNode.setInterface_types(proxyInterfaceTypes);
406 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
407 if (dataTypesEither.isRight()) {
408 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
409 return Either.right(ToscaError.GENERAL_ERROR);
411 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
412 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
413 List<InputDefinition> inputDef = component.getInputs();
414 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
415 if (!inputs.isEmpty()) {
416 topologyTemplate.setInputs(inputs);
418 final Map<String, ToscaProperty> outputs;
420 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
421 } catch (final ToscaConversionException e) {
422 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
423 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
424 return Either.right(ToscaError.GENERAL_ERROR);
426 if (!outputs.isEmpty()) {
427 topologyTemplate.setOutputs(outputs);
429 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
430 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
431 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
432 if (nodeTemplates.isRight()) {
433 return Either.right(nodeTemplates.right().value());
435 log.debug("node templates converted");
436 topologyTemplate.setNode_templates(nodeTemplates.left().value());
438 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
439 .createFrom(topologyTemplate.getNode_templates());
440 if (!relationshipTemplatesMap.isEmpty()) {
441 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
443 addGroupsToTopologyTemplate(component, topologyTemplate);
445 addPoliciesToTopologyTemplate(component, topologyTemplate);
446 } catch (SdcResourceNotFoundException e) {
447 log.debug("Fail to add policies to topology template:", e);
448 return Either.right(ToscaError.GENERAL_ERROR);
451 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
452 } catch (final ToscaExportException e) {
453 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
454 return Either.right(e.getToscaError());
456 if (!topologyTemplate.isEmpty()) {
457 toscaNode.setTopology_template(topologyTemplate);
459 return Either.left(toscaNode);
462 private Either<String, ToscaError> createComponentToscaName(final Component component) {
463 switch (component.getComponentType()) {
465 final ResourceMetadataDataDefinition resourceMetadata =
466 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
467 return Either.left(resourceMetadata.getToscaResourceName());
469 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
471 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
472 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
476 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
477 final Map<String, Component> componentCache) throws ToscaExportException {
478 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
479 return Optional.empty();
482 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
483 if (toscaResourceNameEither.isRight()) {
484 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
486 final String toscaResourceName = toscaResourceNameEither.left().value();
488 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
489 if (doNotExtendBaseType(component)) {
490 substitutionMapping.setNode_type(component.getDerivedFromGenericType());
492 substitutionMapping.setNode_type(toscaResourceName);
494 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
496 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
497 if (capabilitiesEither.isRight()) {
498 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
500 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
501 if (!capabilityMap.isEmpty()) {
502 substitutionMapping.setCapabilities(capabilityMap);
504 final Either<Map<String, String[]>, ToscaError> requirements =
505 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
506 if (requirements.isRight()) {
507 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
509 final Map<String, String[]> requirementMap = requirements.left().value();
510 if (MapUtils.isNotEmpty(requirementMap)) {
511 substitutionMapping.setRequirements(requirementMap);
514 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
515 if (MapUtils.isNotEmpty(propertyMappingMap)) {
516 substitutionMapping.setProperties(propertyMappingMap);
519 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
520 if (MapUtils.isNotEmpty(attributesMappingMap)) {
521 substitutionMapping.setAttributes(attributesMappingMap);
524 return Optional.of(substitutionMapping);
527 private boolean doNotExtendBaseType(final Component component) {
528 final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig = ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
529 List<CategoryDefinition> categories = component.getCategories();
530 if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig) && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
531 return serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
536 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
537 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
538 return Optional.empty();
541 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
544 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
545 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
546 if (groups != null) {
547 topologyTemplate.addGroups(groups);
551 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
552 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
553 if (policies != null) {
554 topologyTemplate.addPolicies(policies);
558 private Map<String, String> convertMetadata(Component component) {
559 return convertMetadata(component, false, null);
562 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
563 Map<String, String> toscaMetadata = new LinkedHashMap<>();
564 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
565 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
567 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
568 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
569 List<CategoryDefinition> categories = component.getCategories();
570 CategoryDefinition categoryDefinition = categories.get(0);
571 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
572 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
574 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
575 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
576 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
577 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
578 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
579 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
580 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
581 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
582 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
583 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
584 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
585 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
586 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
588 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
591 switch (component.getComponentType()) {
593 Resource resource = (Resource) component;
594 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
595 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
596 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
598 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
600 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
601 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
602 if (resource.getTenant() != null) {
603 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
605 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
606 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
609 Service service = (Service) component;
610 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
611 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
612 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
613 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
614 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
615 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
616 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
619 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
620 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
621 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
625 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
627 for (final String key : component.getCategorySpecificMetadata().keySet()) {
628 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
629 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
632 return toscaMetadata;
635 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
636 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
637 return INVARIANT_UUID;
639 return jsonPresentationField.getPresentation();
642 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
643 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
644 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
645 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
646 return Either.right(ToscaError.GENERAL_ERROR);
648 Map<String, Component> componentCache = new HashMap<>();
649 if (!ModelConverter.isAtomicComponent(component)) {
650 final List<Map<String, Map<String, String>>> additionalImports =
651 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
652 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
653 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
654 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
655 if (!substituteTypeImportEntry.isEmpty()) {
656 additionalImports.add(substituteTypeImportEntry);
658 List<ComponentInstance> componentInstances = component.getComponentInstances();
659 if (componentInstances != null && !componentInstances.isEmpty()) {
660 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
662 toscaTemplate.setDependencies(dependencies);
663 toscaTemplate.setImports(additionalImports);
665 log.debug("currently imports supported for VF and service only");
667 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
670 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
671 final Map<String, ArtifactDefinition> toscaArtifacts) {
672 if (doNotExtendBaseType(component)) {
673 return Collections.emptyMap();
675 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
676 return Collections.emptyMap();
678 if (MapUtils.isEmpty(toscaArtifacts)) {
679 return Collections.emptyMap();
681 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
682 if (artifactDefinition == null) {
683 return Collections.emptyMap();
685 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
686 return Map.of(importEntryName,
687 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
691 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
692 return getConfiguration().getDefaultImports();
695 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
696 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
697 log.debug("createDependency componentCache {}", componentCache);
698 Component componentRI = componentCache.get(componentInstance.getComponentUid());
699 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
700 // all resource must be only once!
701 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
702 if ((resource.isRight()) && (log.isDebugEnabled())) {
703 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
704 componentInstance.getUniqueId());
707 final Component fetchedComponent = resource.left().value();
708 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
709 addDependencies(imports, dependencies, componentRI);
714 * Sets a componentCache from the given component/resource.
716 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
717 final Component fetchedComponent) {
718 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
719 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
720 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
721 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
722 .getToscaFullElement(componentInstance.getSourceModelUid());
723 if (sourceService.isRight() && (log.isDebugEnabled())) {
724 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
725 componentInstance.getUniqueId());
727 final Component fetchedSource = sourceService.left().value();
728 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
729 return fetchedSource;
731 return fetchedComponent;
735 * Retrieves all derived_from nodes and stores it in a predictable order.
737 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
738 final Component fetchedComponent) {
739 final Set<Component> componentsList = new LinkedHashSet<>();
740 if (fetchedComponent instanceof Resource) {
741 log.debug("fetchedComponent is a resource {}", fetchedComponent);
742 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
743 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
744 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
745 log.debug("Started entry.getValue() : {}", entry.getValue());
746 if (!NATIVE_ROOT.equals(entry.getValue())) {
747 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
748 if (resourcefetched != null && resourcefetched.isLeft()) {
749 componentsList.add(resourcefetched.left().value());
753 setImports(imports, dependencies, componentsList);
755 setImports(imports, dependencies, fetchedComponent);
761 * Returns all derived_from nodes found.
763 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
764 final Resource parentResource = (Resource) fetchedComponent;
765 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
766 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
767 componentsList.add(fetchedComponent);
768 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
769 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
770 .getToscaElement(componentInstance.getComponentUid());
771 if (resourcefetched != null && resourcefetched.isLeft()) {
772 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
773 if (MapUtils.isNotEmpty(derivedWithId)) {
774 derivedFromMapOfIdToName.putAll(derivedWithId);
779 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
781 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
782 return Optional.ofNullable(derivedFromMapOfIdToName);
786 * Creates a resource map and adds it to the import list.
788 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
789 final Set<Component> componentsList) {
790 componentsList.forEach(component -> setImports(imports, dependencies, component));
793 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
794 final Component component) {
795 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
796 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
797 if (artifactDefinition != null) {
798 final Map<String, String> files = new HashMap<>();
799 final String artifactName = artifactDefinition.getArtifactName();
800 files.put(IMPORTS_FILE_KEY, artifactName);
801 final StringBuilder keyNameBuilder = new StringBuilder();
802 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
803 keyNameBuilder.append("-");
804 keyNameBuilder.append(component.getName());
805 addImports(imports, keyNameBuilder, files);
806 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
807 if (!ModelConverter.isAtomicComponent(component)) {
808 final Map<String, String> interfaceFiles = new HashMap<>();
809 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
810 keyNameBuilder.append("-interface");
811 addImports(imports, keyNameBuilder, interfaceFiles);
817 * Adds the found resource to the import definition list.
819 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
820 final Map<String, String> files) {
821 final String mapKey = keyNameBuilder.toString();
822 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
823 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
824 importsListMember.put(keyNameBuilder.toString(), files);
825 imports.add(importsListMember);
829 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
830 Map<String, ToscaNodeType> nodeTypes) {
831 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
834 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
835 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
836 boolean isAssociatedComponent) {
837 log.debug("start convert node type for {}", component.getUniqueId());
838 ToscaNodeType toscaNodeType = createNodeType(component);
839 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
840 .getAllInterfaceLifecycleTypes(component.getModel());
841 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
842 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
843 return Either.right(ToscaError.GENERAL_ERROR);
845 if (lifecycleTypeEither.isLeft()) {
846 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
847 .collect(Collectors.toList());
848 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
850 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
851 if (dataTypesEither.isRight()) {
852 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
853 return Either.right(ToscaError.GENERAL_ERROR);
855 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
856 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
857 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
858 if (!toscaAttributeMap.isEmpty()) {
859 toscaNodeType.setAttributes(toscaAttributeMap);
861 Map<String, ToscaProperty> convertedProperties = new HashMap();
862 if (CollectionUtils.isNotEmpty(component.getProperties())) {
863 List<PropertyDefinition> properties = component.getProperties();
864 convertedProperties = properties.stream()
865 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
866 .toMap(PropertyDataDefinition::getName,
867 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
869 if (MapUtils.isNotEmpty(convertedProperties)) {
870 toscaNodeType.setProperties(convertedProperties);
872 /* convert private data_types */
873 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
874 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
875 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
876 for (DataTypeDefinition dataType : privateDataTypes) {
877 log.debug("Emitting private data type: component.name={} dataType.name={}",
878 component.getNormalizedName(), dataType.getName());
879 ToscaDataType toscaDataType = new ToscaDataType();
880 toscaDataType.setDerived_from(dataType.getDerivedFromName());
881 toscaDataType.setDescription(dataType.getDescription());
882 toscaDataType.setVersion(dataType.getVersion());
883 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
884 toscaDataType.setProperties(dataType.getProperties().stream()
885 .collect(Collectors.toMap(
886 PropertyDataDefinition::getName,
887 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
888 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
892 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
894 toscaNode.setData_types(toscaDataTypeMap);
897 // Extracted to method for code reuse
898 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
901 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
902 final ToscaProperty toscaProperty) {
903 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
904 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
905 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
908 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
909 final Map<String, DataTypeDefinition> dataTypes) {
910 if (CollectionUtils.isEmpty(attributeList)) {
911 return Collections.emptyMap();
913 final AttributeConverter converter = new AttributeConverter(dataTypes);
914 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
915 for (final AttributeDefinition attributeDefinition : attributeList) {
916 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
918 return toscaAttributeMap;
921 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
922 Component component, ToscaTemplate toscaNode,
923 Map<String, ToscaNodeType> nodeTypes,
924 ToscaNodeType toscaNodeType,
925 Map<String, DataTypeDefinition> dataTypes) {
926 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
928 if (capabilities.isRight()) {
929 return Either.right(capabilities.right().value());
931 toscaNodeType = capabilities.left().value();
932 log.debug("Capabilities converted for {}", component.getUniqueId());
934 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
935 .convertRequirements(componentsCache, component, toscaNodeType);
936 if (requirements.isRight()) {
937 return Either.right(requirements.right().value());
939 toscaNodeType = requirements.left().value();
940 log.debug("Requirements converted for {}", component.getUniqueId());
942 String toscaResourceName;
943 switch (component.getComponentType()) {
945 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
946 .getMetadataDataDefinition()).getToscaResourceName();
949 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
950 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
953 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
954 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
957 nodeTypes.put(toscaResourceName, toscaNodeType);
958 toscaNode.setNode_types(nodeTypes);
959 log.debug("finish convert node type for {}", component.getUniqueId());
960 return Either.left(toscaNode);
963 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
964 final Map<String, Component> componentCache,
965 final Map<String, DataTypeDefinition> dataTypes,
966 final ToscaTopolgyTemplate topologyTemplate) {
968 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
969 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
970 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
971 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
972 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
974 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
975 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
976 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
978 Map<String, ToscaGroupTemplate> groupsMap = null;
979 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
980 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
981 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
982 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
984 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
985 List<Object> occur = new ArrayList<>();
986 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
987 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
988 nodeTemplate.setOccurrences(occur);
990 if (componentInstance.getInstanceCount() != null) {
991 ObjectMapper objectMapper = new ObjectMapper();
992 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
994 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
995 nodeTemplate.setInstance_count(map);
998 nodeTemplate.setType(componentInstance.getToscaComponentName());
999 nodeTemplate.setDirectives(componentInstance.getDirectives());
1000 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1001 if (nodeFilter != null && nodeFilter.hasData()) {
1002 nodeTemplate.setNode_filter(nodeFilter);
1004 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1005 .getOriginComponent(componentCache, componentInstance);
1006 if (originComponentRes.isRight()) {
1007 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1010 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1011 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1012 if (requirements.isRight()) {
1013 convertNodeTemplatesRes = Either.right(requirements.right().value());
1016 final String instanceUniqueId = componentInstance.getUniqueId();
1017 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1019 nodeTemplate = requirements.left().value();
1021 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1023 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1024 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1025 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1027 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1030 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1031 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1032 if (capabilities.isRight()) {
1033 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1036 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1038 nodeTemplate = capabilities.left().value();
1039 final Map<String, Object> props = new HashMap<>();
1040 final Map<String, Object> attribs = new HashMap<>();
1042 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1043 // Adds the properties of parent component to map
1044 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1045 addAttributesOfParentComponent(originalComponent, attribs);
1048 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1049 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1051 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1052 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1055 if (componentInstancesInputs != null
1056 && componentInstancesInputs.containsKey(instanceUniqueId)
1057 && !isComponentOfTypeServiceProxy(componentInstance)) {
1058 //For service proxy the inputs are already handled under instance properties above
1059 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1062 //M3[00001] - NODE TEMPLATE INTERFACES - START
1063 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1064 //M3[00001] - NODE TEMPLATE INTERFACES - END
1065 if (MapUtils.isNotEmpty(props)) {
1066 nodeTemplate.setProperties(props);
1068 if (MapUtils.isNotEmpty(attribs)) {
1069 nodeTemplate.setAttributes(attribs);
1072 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1073 if (CollectionUtils.isNotEmpty(groupInstances)) {
1074 if (groupsMap == null) {
1075 groupsMap = new HashMap<>();
1077 for (final GroupInstance groupInst : groupInstances) {
1078 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1079 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1084 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1086 if (groupsMap != null) {
1087 log.debug("instance groups added");
1088 topologyTemplate.addGroups(groupsMap);
1090 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1091 ((Service) component).getForwardingPaths())) {
1092 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1093 ForwardingPathToscaUtil
1094 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1095 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1097 if (convertNodeTemplatesRes == null) {
1098 convertNodeTemplatesRes = Either.left(nodeTemplates);
1100 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1101 return convertNodeTemplatesRes;
1104 private Object convertToToscaObject(String value) {
1106 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1107 StringReader reader = new StringReader(value);
1108 JsonReader jsonReader = new JsonReader(reader);
1109 jsonReader.setLenient(true);
1110 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1111 if (jsonElement.isJsonObject()) {
1112 JsonObject jsonObj = jsonElement.getAsJsonObject();
1113 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1114 return mapConverterInst.handleComplexJsonValue(jsonElement);
1118 } catch (Exception e) {
1119 log.debug("convertToToscaValue failed to parse json value :", e);
1124 private Object parseToIntIfPossible(final String value) {
1125 final Integer intValue = Ints.tryParse(value);
1126 return intValue == null ? value : intValue;
1129 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1130 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1131 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1133 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1134 nodeTemplate.setInterfaces(null);
1138 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1140 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1141 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1143 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1144 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1146 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1147 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1150 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1151 return Objects.nonNull(componentInstance.getOriginType())
1152 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1155 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1156 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1157 String instanceUniqueId, Map<String, Object> props) {
1159 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1160 if (instanceInputsList != null) {
1161 instanceInputsList.forEach(input -> {
1162 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1163 : input.getDefaultValue();
1164 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1169 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1170 final Map<String, DataTypeDefinition> dataTypes,
1171 final String instanceUniqueId,
1172 final Map<String, Object> props) {
1174 if (isNotEmpty(componentInstancesProperties)) {
1175 componentInstancesProperties.get(instanceUniqueId)
1176 // Converts and adds each value to property map
1177 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1181 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1182 final String instanceUniqueId,
1183 final Map<String, Object> attribs) {
1185 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1186 componentInstancesAttributes.get(instanceUniqueId)
1187 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1191 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1192 Component componentOfInstance, Map<String, Object> props) {
1194 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1195 if (isNotEmpty(componentProperties)) {
1196 componentProperties.stream()
1197 // Filters out properties with empty default values
1198 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1199 // Converts and adds each value to property map
1200 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1204 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1206 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1207 if (isNotEmpty(componentAttributes)) {
1208 componentAttributes.stream()
1209 // Filters out Attributes with empty default values
1210 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1211 // Converts and adds each value to attribute map
1212 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1216 private ToscaNodeType createNodeType(Component component) {
1217 ToscaNodeType toscaNodeType = new ToscaNodeType();
1218 if (ModelConverter.isAtomicComponent(component)) {
1219 if (((Resource) component).getDerivedFrom() != null) {
1220 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1222 toscaNodeType.setDescription(component.getDescription());
1224 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1226 toscaNodeType.setDerived_from(derivedFrom);
1228 return toscaNodeType;
1231 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1233 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1234 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1235 List<ComponentInstance> componentInstances = container.getComponentInstances();
1236 if (CollectionUtils.isEmpty(componentInstances)) {
1239 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1240 componentInstances.stream()
1241 .filter(this::isComponentOfTypeServiceProxy)
1242 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1243 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1246 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1247 Component serviceComponent;
1248 ComponentParametersView componentParametersView = new ComponentParametersView();
1249 componentParametersView.disableAll();
1250 componentParametersView.setIgnoreInterfaces(false);
1251 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1252 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1253 if (service.isRight()) {
1254 log.debug("Failed to fetch original service component with id {} for instance {}",
1255 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1256 return Either.right(ToscaError.GENERAL_ERROR);
1258 serviceComponent = service.left().value();
1261 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1262 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1263 if (lifecycleTypeEither.isRight()) {
1264 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1265 return Either.right(ToscaError.GENERAL_ERROR);
1268 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1269 .map(InterfaceDataDefinition::getType)
1270 .collect(Collectors.toList());
1271 //Add interface types for local interfaces in the original service component for proxy
1272 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1273 allGlobalInterfaceTypes);
1274 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1275 proxyInterfaceTypes.putAll(localInterfaceTypes);
1279 return Either.left(proxyInterfaceTypes);
1282 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1283 Component container) {
1285 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1286 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1288 List<ComponentInstance> componentInstances = container.getComponentInstances();
1290 if (componentInstances == null || componentInstances.isEmpty()) {
1293 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1294 List<ComponentInstance> proxyInst = componentInstances.stream()
1295 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1296 .collect(Collectors.toList());
1297 if (proxyInst != null && !proxyInst.isEmpty()) {
1298 for (ComponentInstance inst : proxyInst) {
1299 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1303 if (serviceProxyInstanceList.isEmpty()) {
1306 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1307 .getLatestByName("serviceProxy", null);
1308 if (serviceProxyOrigin.isRight()) {
1309 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1310 serviceProxyOrigin.right().value());
1311 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1313 Component origComponent = serviceProxyOrigin.left().value();
1315 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1316 Component serviceComponent = null;
1317 ComponentParametersView componentParametersView = new ComponentParametersView();
1318 componentParametersView.disableAll();
1319 componentParametersView.setIgnoreCategories(false);
1320 componentParametersView.setIgnoreProperties(false);
1321 componentParametersView.setIgnoreInputs(false);
1322 componentParametersView.setIgnoreInterfaces(false);
1323 componentParametersView.setIgnoreRequirements(false);
1324 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1325 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1326 if (service.isRight()) {
1327 log.debug("Failed to fetch resource with id {} for instance {}",
1328 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1330 serviceComponent = service.left().value();
1333 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1334 entryProxy.getValue());
1335 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1338 return Either.left(nodeTypesMap);
1341 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1342 final Component container, final ToscaTemplate toscaNode) {
1343 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1345 if (CollectionUtils.isEmpty(componentInstances)) {
1348 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1349 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1350 .collect(Collectors.toList());
1351 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1352 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1353 final Map<String, ToscaNodeType> nodeTypes =
1354 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1355 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1361 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1362 Component proxyComponent, ComponentInstance componentInstance) {
1363 ToscaNodeType toscaNodeType = new ToscaNodeType();
1364 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1366 toscaNodeType.setDerived_from(derivedFrom);
1367 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1368 origComponent.getModel());
1369 if (dataTypesEither.isRight()) {
1370 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1372 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1373 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1374 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1376 if (MapUtils.isNotEmpty(capabilities)) {
1377 toscaNodeType.setCapabilities(capabilities);
1379 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1380 .convertProxyRequirements(componentCache, componentInstance);
1381 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1382 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1384 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1385 proxyProperties.ifPresent(toscaNodeType::setProperties);
1387 Map<String, Object> interfaceMap = new HashMap<>();
1388 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1389 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1390 if (proxyInterfaces.isPresent()) {
1391 interfaceMap = proxyInterfaces.get();
1394 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1397 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1398 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1400 return toscaNodeType;
1403 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1404 ComponentInstance componentInstance,
1405 List<RequirementCapabilityRelDef> relations,
1406 ToscaNodeTemplate nodeTypeTemplate,
1407 Component originComponent,
1408 Map<String, Component> componentCache) {
1410 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1412 if (isNotEmpty(requirementDefinitionList)) {
1414 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1415 requirementDefinitionList, originComponent, componentCache);
1416 if (!toscaRequirements.isEmpty()) {
1417 nodeTypeTemplate.setRequirements(toscaRequirements);
1419 } catch (final Exception e) {
1420 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1421 componentInstance.getName(), e);
1422 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1425 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1426 return Either.left(nodeTypeTemplate);
1429 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1430 final ComponentInstance componentInstance,
1431 final List<RequirementCapabilityRelDef> filteredRelations,
1432 final Component originComponent,
1433 final Map<String, Component> componentCache)
1434 throws ToscaExportException {
1436 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1437 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1438 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1439 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1440 toscaRequirements.add(toscaTemplateRequirementMap);
1443 return toscaRequirements;
1446 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1447 List<RequirementCapabilityRelDef> relations) {
1448 return relations.stream()
1449 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1452 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1453 final Component fromOriginComponent,
1454 final List<ComponentInstance> instancesList,
1455 final RequirementCapabilityRelDef relationshipDefinition,
1456 final Map<String, Component> componentCache)
1457 throws ToscaExportException {
1459 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1460 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1461 .getRelationships().get(0);
1462 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1464 final ComponentInstance toInstance = instancesList.stream()
1465 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1466 .findFirst().orElse(null);
1467 if (toInstance == null) {
1468 final String errorMsg = String
1469 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1470 relationshipDefinition.getToNode());
1471 log.debug(errorMsg);
1472 throw new ToscaExportException(errorMsg);
1474 final Optional<RequirementDefinition> reqOpt =
1475 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1476 if (reqOpt.isEmpty()) {
1477 final String errorMsg = String
1478 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1479 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1480 log.debug(errorMsg);
1481 throw new ToscaExportException(errorMsg);
1483 final ComponentParametersView filter = new ComponentParametersView(true);
1484 filter.setIgnoreComponentInstances(false);
1485 filter.setIgnoreCapabilities(false);
1486 filter.setIgnoreGroups(false);
1487 final Either<Component, StorageOperationStatus> getOriginRes =
1488 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1489 if (getOriginRes.isRight()) {
1490 final String errorMsg = String.format(
1491 "Failed to build substituted name for the requirement %s. "
1492 + "Failed to get an origin component with uniqueId %s",
1493 reqOpt.get().getName(), toInstance.getActualComponentUid());
1494 log.debug(errorMsg);
1495 throw new ToscaExportException(errorMsg);
1497 final Component toOriginComponent = getOriginRes.left().value();
1498 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1499 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1500 if (capOpt.isEmpty()) {
1501 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1502 if (capOpt.isEmpty()) {
1503 final String errorMsg = String
1504 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1505 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1506 log.debug(errorMsg);
1507 throw new ToscaExportException(errorMsg);
1510 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1511 capabilityRequirementRelationship, toInstance, componentCache);
1514 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1515 CapabilityDefinition capability) {
1516 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1517 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1520 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1521 Component toOriginComponent, Component fromOriginComponent,
1522 RequirementDefinition requirement) {
1523 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1524 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1525 if (!cap.isPresent()) {
1526 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1527 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1532 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1533 final Component toOriginComponent,
1534 final CapabilityDefinition capability,
1535 final RequirementDefinition requirement,
1536 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1537 final ComponentInstance toInstance,
1538 final Map<String, Component> componentCache)
1539 throws ToscaExportException {
1541 List<String> reducedPath = capability.getPath();
1542 if (capability.getOwnerId() != null) {
1543 reducedPath = capabilityRequirementConverter
1544 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1546 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1547 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1548 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1549 if (capabilityNameEither.isRight()) {
1550 final String errorMsg = String.format(
1551 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1552 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1555 throw new ToscaExportException(errorMsg);
1557 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1558 .buildSubstitutedName(componentCache, fromOriginComponent,
1559 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1560 if (requirementNameEither.isRight()) {
1561 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1562 + "with name %s on a component with uniqueId %s",
1563 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1564 log.debug(errorMsg);
1565 throw new ToscaExportException(errorMsg);
1567 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1568 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1569 toscaRequirement.setNode(toInstance.getName());
1570 toscaRequirement.setCapability(capabilityNameEither.left().value());
1571 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1572 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1574 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1578 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1579 Map<String, List<RequirementDefinition>> reqMap,
1580 RelationshipInfo reqAndRelationshipPair,
1581 String fromInstanceId) {
1582 for (List<RequirementDefinition> reqList : reqMap.values()) {
1583 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1584 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1586 if (reqOpt.isPresent()) {
1590 return Optional.empty();
1594 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1595 * 1.The name of the requirement equals to the "requirement" field of the relation; AND 2. In case of a non-atomic resource, OwnerId of the
1596 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1598 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1599 RequirementDefinition requirement, String fromInstanceId) {
1600 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1603 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1604 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1605 reqAndRelationshipPair.getRequirement());
1608 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1612 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1613 Component originComponent) {
1614 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1615 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1616 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1619 private boolean isCvfc(Component component) {
1620 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1623 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1624 final Map<String, Component> componentCache) {
1625 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1626 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1627 if (toscaCapabilitiesRes.isRight()) {
1628 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1629 return Either.right(toscaCapabilitiesRes.right().value());
1631 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1632 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1633 return Either.left(toscaCapabilitiesRes.left().value());
1635 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1637 return Either.left(Collections.emptyMap());
1640 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1641 Map<String, DataTypeDefinition> dataTypes) {
1642 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1643 if (!toscaCapabilities.isEmpty()) {
1644 nodeType.setCapabilities(toscaCapabilities);
1646 log.debug("Finish convert Capabilities for node type");
1647 return Either.left(nodeType);
1650 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1651 if (artifacts == null) {
1654 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1655 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1656 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1657 artifact.setFile(entry.getValue().getFile());
1658 artifact.setType(entry.getValue().getType());
1659 artifact.setProperties(entry.getValue().getProperties());
1660 arts.put(entry.getKey(), artifact);
1665 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1666 if (inNodeFilter == null) {
1669 NodeFilter nodeFilter = new NodeFilter();
1670 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1671 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1672 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1673 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1674 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1675 nodeFilter.setCapabilities(capabilitiesCopy);
1677 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1678 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1679 nodeFilter.setProperties(propertiesCopy);
1681 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1682 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1686 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1687 if (substitutionFilterDataDefinition == null) {
1690 NodeFilter nodeFilter = new NodeFilter();
1691 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1692 if (!propertiesCopy.isEmpty()) {
1693 nodeFilter.setProperties(propertiesCopy);
1695 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1696 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1699 private Object cloneToscaId(Object toscaId) {
1700 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1703 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1704 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1705 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1708 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1709 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1710 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1714 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1715 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1716 final var capabilityFilter = new CapabilityFilter();
1717 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1718 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1719 capabilitiesCopy.add(capabilityFilterCopyMap);
1723 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1724 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1725 return Collections.emptyList();
1727 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1728 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1729 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1730 final String propertyName = propertyFilter.getName();
1731 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1732 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1733 if (constraints == null) {
1734 constraints = new ArrayList<>();
1736 constraints.add(buildNodeFilterValue(filterConstraint));
1741 propertyFilterDefinitionMap.entrySet().stream()
1742 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1743 .forEach(propertiesCopy::add);
1744 return propertiesCopy;
1747 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1748 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1750 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1751 return Collections.emptyList();
1753 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1754 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1755 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1756 final String propertyName = propertyFilter.getName();
1757 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1758 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1759 if (constraints == null) {
1760 constraints = new ArrayList<>();
1762 constraints.add(buildNodeFilterValue(filterConstraint));
1767 propertyFilterDefinitionMap.entrySet().stream()
1768 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1769 .forEach(propertiesCopy::add);
1770 return propertiesCopy;
1773 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1774 if (filterConstraint.getValue() instanceof ToscaFunction) {
1775 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1777 if (filterConstraint.getValue() instanceof List) {
1778 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1779 List<Object> toscaFunctionList = new ArrayList<>();
1780 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1781 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1782 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1785 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1786 ToscaType toscaType = ToscaType.getToscaType(
1787 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1788 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1790 else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1791 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1792 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1793 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1795 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1798 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1799 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null ) {
1802 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1805 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1806 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1807 return Collections.emptyMap();
1809 Map<String, String[]> propertyMapping = new HashMap<>();
1810 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1811 Collectors.toList());
1813 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1814 propertyMappedInputList.forEach(inputDefinition -> {
1815 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1816 Optional<PropertyDefinition> property = component.getProperties().stream()
1817 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1818 if (property.isPresent()) {
1819 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1822 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1826 return propertyMapping;
1829 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1830 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1831 return Collections.emptyMap();
1833 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1834 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1837 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1838 if (Objects.isNull(proxyComponent)) {
1839 return Optional.empty();
1841 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1842 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1843 proxyProperties.putAll(proxyComponent.getProperties().stream()
1844 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1845 .toMap(PropertyDataDefinition::getName,
1846 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1848 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1851 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1852 String componentUniqueId) {
1853 if (CollectionUtils.isEmpty(componentInputs)) {
1854 return new HashMap<>();
1856 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1857 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1860 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1861 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1862 return Optional.empty();
1864 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1865 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1867 // always available in the proxy node template
1868 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1869 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1872 private Configuration getConfiguration() {
1873 return ConfigurationManager.getConfigurationManager().getConfiguration();
1876 private static class CustomRepresenter extends Representer {
1878 CustomRepresenter() {
1880 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1881 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1882 // null representer is exceptional and it is stored as an instance
1885 this.nullRepresenter = new RepresentNull();
1888 public boolean validateGetInputValue(final Object valueObj) {
1889 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1892 if (valueObj instanceof List) {
1893 return ((List) valueObj).size() > 1;
1898 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1899 if (valueObj instanceof List) {
1900 return ((List) valueObj).size() > 1;
1906 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1907 if (propertyValue == null) {
1910 // skip not relevant for Tosca property
1911 if ("dependencies".equals(property.getName())) {
1914 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1917 if (javaBean instanceof ToscaPropertyConstraint) {
1918 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1920 removeDefaultP(propertyValue);
1921 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1922 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1923 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1925 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1928 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1929 final Tag customTag) {
1930 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1931 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1932 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1935 private void removeDefaultP(final Object propertyValue) {
1936 if (propertyValue instanceof Map) {
1937 final Map mapPropertyValue = ((Map) propertyValue);
1938 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1939 Object defaultValue = null;
1940 while (iter.hasNext()) {
1941 final Map.Entry entry = iter.next();
1942 if ("_defaultp_".equals(entry.getKey())) {
1943 defaultValue = entry.getValue();
1945 } else if (entry.getValue() instanceof Map) {
1946 removeDefaultP(entry.getValue());
1949 if (defaultValue != null) {
1950 mapPropertyValue.putIfAbsent("default", defaultValue);
1956 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1957 // remove the bean type from the output yaml (!! ...)
1958 if (!classTags.containsKey(javaBean.getClass())) {
1959 addClassTag(javaBean.getClass(), Tag.MAP);
1961 return super.representJavaBean(properties, javaBean);
1964 private class RepresentToscaAttribute implements Represent {
1967 public Node representData(Object data) {
1968 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1969 return represent(toscaAttribute.asToscaMap());
1973 private class RepresentToscaPropertyAssignment implements Represent {
1975 public Node representData(Object data) {
1976 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1977 if (toscaOperationAssignment.getValue() instanceof String) {
1978 final String stringValue = (String) toscaOperationAssignment.getValue();
1979 if (isPropertyOrAttributeFunction(stringValue)) {
1980 return representGetAttribute(stringValue);
1982 return representScalar(Tag.STR, stringValue);
1984 return represent(null);
1987 public Node representGetAttribute(final String getAttributeFunction) {
1988 return represent(new Yaml().load(getAttributeFunction));
1991 public boolean isPropertyOrAttributeFunction(final String value) {
1993 final Yaml yaml = new Yaml();
1994 final Object yamlObj = yaml.load(value);
1995 if (!(yamlObj instanceof Map)) {
1998 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1999 if (getAttributeMap.size() != 1) {
2002 final List<String> functionList = Arrays
2003 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2004 final Optional<String> function = getAttributeMap.keySet().stream()
2005 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2006 if (function.isEmpty()) {
2009 final String functionName = function.get();
2010 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2011 if (GET_INPUT.getFunctionName().equals(functionName)) {
2012 return validateGetInputValue(getAttributeValueObj);
2014 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2016 } catch (final Exception ignored) {
2022 private class RepresentNull implements Represent {
2025 public Node representData(Object data) {
2026 // possible values are here http://yaml.org/type/null.html
2027 return representScalar(Tag.NULL, "");
2032 private static class UnsortedPropertyUtils extends PropertyUtils {
2035 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2036 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2037 return new LinkedHashSet<>(fields);