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;
36 import java.io.StringReader;
37 import java.nio.file.Path;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.LinkedHashMap;
46 import java.util.LinkedHashSet;
47 import java.util.List;
49 import java.util.Map.Entry;
50 import java.util.Objects;
51 import java.util.Optional;
53 import java.util.function.Supplier;
54 import java.util.stream.Collectors;
55 import org.apache.commons.collections.CollectionUtils;
56 import org.apache.commons.collections.MapUtils;
57 import org.apache.commons.io.FilenameUtils;
58 import org.apache.commons.lang3.StringUtils;
59 import org.apache.commons.lang3.tuple.ImmutablePair;
60 import org.apache.commons.lang3.tuple.ImmutableTriple;
61 import org.apache.commons.lang3.tuple.Triple;
62 import org.onap.sdc.tosca.services.YamlUtil;
63 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
64 import org.openecomp.sdc.be.config.Configuration;
65 import org.openecomp.sdc.be.config.ConfigurationManager;
66 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
67 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
68 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
70 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
71 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
81 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
82 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
83 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
84 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
85 import org.openecomp.sdc.be.exception.ToscaExportException;
86 import org.openecomp.sdc.be.model.ArtifactDefinition;
87 import org.openecomp.sdc.be.model.AttributeDefinition;
88 import org.openecomp.sdc.be.model.CapabilityDefinition;
89 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
90 import org.openecomp.sdc.be.model.Component;
91 import org.openecomp.sdc.be.model.ComponentInstance;
92 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
93 import org.openecomp.sdc.be.model.ComponentInstanceInput;
94 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
95 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
96 import org.openecomp.sdc.be.model.ComponentParametersView;
97 import org.openecomp.sdc.be.model.DataTypeDefinition;
98 import org.openecomp.sdc.be.model.GroupInstance;
99 import org.openecomp.sdc.be.model.InputDefinition;
100 import org.openecomp.sdc.be.model.InterfaceDefinition;
101 import org.openecomp.sdc.be.model.PropertyDefinition;
102 import org.openecomp.sdc.be.model.RelationshipInfo;
103 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
104 import org.openecomp.sdc.be.model.RequirementDefinition;
105 import org.openecomp.sdc.be.model.Resource;
106 import org.openecomp.sdc.be.model.Service;
107 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
108 import org.openecomp.sdc.be.model.category.CategoryDefinition;
109 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
110 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
111 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
112 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
113 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
114 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
115 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
116 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
117 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
118 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
119 import org.openecomp.sdc.be.tosca.model.NodeFilter;
120 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
121 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
122 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
123 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
124 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
125 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
126 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
127 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
128 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
129 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
130 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
131 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
132 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
133 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
134 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
135 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
136 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
137 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
138 import org.openecomp.sdc.be.tosca.utils.InputConverter;
139 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
140 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
141 import org.openecomp.sdc.common.log.wrappers.Logger;
142 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
143 import org.springframework.beans.factory.annotation.Autowired;
144 import org.yaml.snakeyaml.DumperOptions;
145 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
146 import org.yaml.snakeyaml.Yaml;
147 import org.yaml.snakeyaml.introspector.BeanAccess;
148 import org.yaml.snakeyaml.introspector.Property;
149 import org.yaml.snakeyaml.introspector.PropertyUtils;
150 import org.yaml.snakeyaml.nodes.MappingNode;
151 import org.yaml.snakeyaml.nodes.Node;
152 import org.yaml.snakeyaml.nodes.NodeTuple;
153 import org.yaml.snakeyaml.nodes.Tag;
154 import org.yaml.snakeyaml.representer.Represent;
155 import org.yaml.snakeyaml.representer.Representer;
157 @org.springframework.stereotype.Component("tosca-export-handler")
158 public class ToscaExportHandler {
160 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
161 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
162 private static final String INVARIANT_UUID = "invariantUUID";
163 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
164 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
165 private static final String IMPORTS_FILE_KEY = "file";
166 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
167 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
168 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
169 private static final String NATIVE_ROOT = "tosca.nodes.Root";
170 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
171 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
172 private static final YamlUtil yamlUtil = new YamlUtil();
173 private final ApplicationDataTypeCache applicationDataTypeCache;
174 private final ToscaOperationFacade toscaOperationFacade;
175 private final CapabilityRequirementConverter capabilityRequirementConverter;
176 private final PolicyExportParser policyExportParser;
177 private final GroupExportParser groupExportParser;
178 private final PropertyConvertor propertyConvertor;
179 private final AttributeConverter attributeConverter;
180 private final InputConverter inputConverter;
181 private final OutputConverter outputConverter;
182 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
183 private final InterfacesOperationsConverter interfacesOperationsConverter;
184 private final ModelOperation modelOperation;
187 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
188 final ToscaOperationFacade toscaOperationFacade,
189 final CapabilityRequirementConverter capabilityRequirementConverter,
190 final PolicyExportParser policyExportParser,
191 final GroupExportParser groupExportParser,
192 final PropertyConvertor propertyConvertor,
193 final AttributeConverter attributeConverter,
194 final InputConverter inputConverter,
195 final OutputConverter outputConverter,
196 final InterfaceLifecycleOperation interfaceLifecycleOperation,
197 final InterfacesOperationsConverter interfacesOperationsConverter,
198 final ModelOperation modelOperation) {
199 this.applicationDataTypeCache = applicationDataTypeCache;
200 this.toscaOperationFacade = toscaOperationFacade;
201 this.capabilityRequirementConverter = capabilityRequirementConverter;
202 this.policyExportParser = policyExportParser;
203 this.groupExportParser = groupExportParser;
204 this.propertyConvertor = propertyConvertor;
205 this.attributeConverter = attributeConverter;
206 this.inputConverter = inputConverter;
207 this.outputConverter = outputConverter;
208 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
209 this.interfacesOperationsConverter = interfacesOperationsConverter;
210 this.modelOperation = modelOperation;
213 public static String getInterfaceFilename(String artifactName) {
214 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
217 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
218 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
221 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
222 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
225 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
226 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
229 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
230 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
231 if (CollectionUtils.isEmpty(imports)) {
232 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
233 return Either.right(ToscaError.GENERAL_ERROR);
235 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
236 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
237 .startsWith("org.openecomp.resource.abstract.nodes.")) {
238 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
239 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
240 component.getModel());
241 if (baseType.isLeft() && baseType.left().value() != null) {
242 addDependencies(imports, dependencies, baseType.left().value());
244 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
248 String toscaVersion = null;
249 if (component instanceof Resource) {
250 toscaVersion = ((Resource) component).getToscaVersion();
252 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
253 toscaTemplate.setImports(imports);
254 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
255 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
256 isAssociatedComponent);
257 if (toscaTemplateRes.isRight()) {
258 return Either.right(toscaTemplateRes.right().value());
260 toscaTemplate = toscaTemplateRes.left().value();
261 toscaTemplate.setDependencies(dependencies);
262 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
263 return Either.left(toscaRepresentation);
266 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
267 CustomRepresenter representer = new CustomRepresenter();
268 DumperOptions options = new DumperOptions();
269 options.setAllowReadOnlyProperties(false);
270 options.setPrettyFlow(true);
271 options.setDefaultFlowStyle(FlowStyle.FLOW);
272 options.setCanonical(false);
273 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
274 representer.setPropertyUtils(new UnsortedPropertyUtils());
277 Yaml yaml = new Yaml(representer, options);
278 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
279 StringBuilder sb = new StringBuilder();
280 sb.append(getConfiguration().getHeatEnvArtifactHeader());
281 sb.append(yamlAsString);
282 sb.append(getConfiguration().getHeatEnvArtifactFooter());
283 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
286 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
287 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
288 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
289 if (fillImports.isRight()) {
290 return Either.right(fillImports.right().value());
292 return Either.left(fillImports.left().value().left);
295 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
296 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
297 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
298 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
299 return Either.right(ToscaError.GENERAL_ERROR);
301 log.trace("start tosca export for {}", component.getUniqueId());
302 String toscaVersion = null;
303 if (component instanceof Resource) {
304 toscaVersion = ((Resource) component).getToscaVersion();
306 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
307 toscaTemplate.setMetadata(convertMetadata(component));
308 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
309 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
310 if (ModelConverter.isAtomicComponent(component)) {
311 log.trace("convert component as node type");
312 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
314 log.trace("convert component as topology template");
315 return convertToscaTemplate(component, toscaTemplate);
319 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
320 if (modelId == null) {
321 return getDefaultToscaImportConfig();
324 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
325 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
326 final Set<Path> addedPathList = new HashSet<>();
327 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
328 var importPath = Path.of(toscaImportByModel.getFullPath());
329 if (addedPathList.contains(importPath)) {
330 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
332 final String fileName = FilenameUtils.getBaseName(importPath.toString());
333 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
334 addedPathList.add(importPath);
339 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
340 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
341 if (importsRes.isRight()) {
342 return Either.right(importsRes.right().value());
344 toscaNode = importsRes.left().value().left;
345 Map<String, Component> componentCache = importsRes.left().value().right;
346 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
347 if (nodeTypesMapEither.isRight()) {
348 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
349 return Either.right(nodeTypesMapEither.right().value());
351 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
352 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
353 toscaNode.setNode_types(nodeTypesMap);
355 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
356 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
357 if (proxyInterfaceTypesEither.isRight()) {
358 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
359 return Either.right(proxyInterfaceTypesEither.right().value());
361 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
362 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
363 toscaNode.setInterface_types(proxyInterfaceTypes);
365 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
366 if (dataTypesEither.isRight()) {
367 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
368 return Either.right(ToscaError.GENERAL_ERROR);
370 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
371 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
372 List<InputDefinition> inputDef = component.getInputs();
373 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
374 if (!inputs.isEmpty()) {
375 topologyTemplate.setInputs(inputs);
377 final Map<String, ToscaProperty> outputs;
379 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
380 } catch (final ToscaConversionException e) {
381 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
382 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
383 return Either.right(ToscaError.GENERAL_ERROR);
385 if (!outputs.isEmpty()) {
386 topologyTemplate.setOutputs(outputs);
388 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
389 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
390 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
391 if (nodeTemplates.isRight()) {
392 return Either.right(nodeTemplates.right().value());
394 log.debug("node templates converted");
395 topologyTemplate.setNode_templates(nodeTemplates.left().value());
397 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
398 .createFrom(topologyTemplate.getNode_templates());
399 if (!relationshipTemplatesMap.isEmpty()) {
400 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
402 addGroupsToTopologyTemplate(component, topologyTemplate);
404 addPoliciesToTopologyTemplate(component, topologyTemplate);
405 } catch (SdcResourceNotFoundException e) {
406 log.debug("Fail to add policies to topology template:", e);
407 return Either.right(ToscaError.GENERAL_ERROR);
410 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
411 } catch (final ToscaExportException e) {
412 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
413 return Either.right(e.getToscaError());
415 if (!topologyTemplate.isEmpty()) {
416 toscaNode.setTopology_template(topologyTemplate);
418 return Either.left(toscaNode);
421 private Either<String, ToscaError> createComponentToscaName(final Component component) {
422 switch (component.getComponentType()) {
424 final ResourceMetadataDataDefinition resourceMetadata =
425 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
426 return Either.left(resourceMetadata.getToscaResourceName());
428 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
430 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
431 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
435 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
436 final Map<String, Component> componentCache) throws ToscaExportException {
437 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
438 return Optional.empty();
441 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
442 if (toscaResourceNameEither.isRight()) {
443 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
445 final String toscaResourceName = toscaResourceNameEither.left().value();
447 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
448 substitutionMapping.setNode_type(toscaResourceName);
449 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
451 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
452 if (capabilitiesEither.isRight()) {
453 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
455 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
456 if (!capabilityMap.isEmpty()) {
457 substitutionMapping.setCapabilities(capabilityMap);
460 final Either<Map<String, String[]>, ToscaError> requirements =
461 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
462 if (requirements.isRight()) {
463 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
465 final Map<String, String[]> requirementMap = requirements.left().value();
466 if (MapUtils.isNotEmpty(requirementMap)) {
467 substitutionMapping.setRequirements(requirementMap);
470 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
471 if (MapUtils.isNotEmpty(propertyMappingMap)) {
472 substitutionMapping.setProperties(propertyMappingMap);
475 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
476 if (MapUtils.isNotEmpty(attributesMappingMap)) {
477 substitutionMapping.setAttributes(attributesMappingMap);
480 return Optional.of(substitutionMapping);
483 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
484 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
485 return Optional.empty();
488 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
491 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
492 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
493 if (groups != null) {
494 topologyTemplate.addGroups(groups);
498 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
499 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
500 if (policies != null) {
501 topologyTemplate.addPolicies(policies);
505 private Map<String, String> convertMetadata(Component component) {
506 return convertMetadata(component, false, null);
509 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
510 Map<String, String> toscaMetadata = new LinkedHashMap<>();
511 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
512 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
514 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
515 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
516 List<CategoryDefinition> categories = component.getCategories();
517 CategoryDefinition categoryDefinition = categories.get(0);
518 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
519 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
521 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
522 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
523 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
524 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
525 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
526 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
527 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
528 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
529 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
530 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
531 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
532 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
533 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
535 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
538 switch (component.getComponentType()) {
540 Resource resource = (Resource) component;
541 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
542 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
543 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
545 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
547 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
548 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
549 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
550 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
553 Service service = (Service) component;
554 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
555 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
556 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
557 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
558 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
559 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
560 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
563 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
564 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
565 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
569 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
571 for (final String key : component.getCategorySpecificMetadata().keySet()) {
572 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
573 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
576 return toscaMetadata;
579 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
580 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
581 return INVARIANT_UUID;
583 return jsonPresentationField.getPresentation();
586 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
587 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
588 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
589 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
590 return Either.right(ToscaError.GENERAL_ERROR);
592 Map<String, Component> componentCache = new HashMap<>();
593 if (!ModelConverter.isAtomicComponent(component)) {
594 final List<Map<String, Map<String, String>>> additionalImports =
595 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
596 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
597 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
598 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
599 if (!substituteTypeImportEntry.isEmpty()) {
600 additionalImports.add(substituteTypeImportEntry);
602 List<ComponentInstance> componentInstances = component.getComponentInstances();
603 if (componentInstances != null && !componentInstances.isEmpty()) {
604 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
606 toscaTemplate.setDependencies(dependencies);
607 toscaTemplate.setImports(additionalImports);
609 log.debug("currently imports supported for VF and service only");
611 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
614 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
615 final Map<String, ArtifactDefinition> toscaArtifacts) {
617 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
618 return Collections.emptyMap();
620 if (MapUtils.isEmpty(toscaArtifacts)) {
621 return Collections.emptyMap();
623 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
624 if (artifactDefinition == null) {
625 return Collections.emptyMap();
627 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
628 return Map.of(importEntryName,
629 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
633 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
634 return getConfiguration().getDefaultImports();
637 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
638 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
639 log.debug("createDependency componentCache {}", componentCache);
640 Component componentRI = componentCache.get(componentInstance.getComponentUid());
641 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
642 // all resource must be only once!
643 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
644 if ((resource.isRight()) && (log.isDebugEnabled())) {
645 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
646 componentInstance.getUniqueId());
649 final Component fetchedComponent = resource.left().value();
650 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
651 addDependencies(imports, dependencies, componentRI);
656 * Sets a componentCache from the given component/resource.
658 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
659 final Component fetchedComponent) {
660 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
661 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
662 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
663 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
664 .getToscaFullElement(componentInstance.getSourceModelUid());
665 if (sourceService.isRight() && (log.isDebugEnabled())) {
666 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
667 componentInstance.getUniqueId());
669 final Component fetchedSource = sourceService.left().value();
670 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
671 return fetchedSource;
673 return fetchedComponent;
677 * Retrieves all derived_from nodes and stores it in a predictable order.
679 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
680 final Component fetchedComponent) {
681 final Set<Component> componentsList = new LinkedHashSet<>();
682 if (fetchedComponent instanceof Resource) {
683 log.debug("fetchedComponent is a resource {}", fetchedComponent);
684 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
685 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
686 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
687 log.debug("Started entry.getValue() : {}", entry.getValue());
688 if (!NATIVE_ROOT.equals(entry.getValue())) {
689 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
690 if (resourcefetched != null && resourcefetched.isLeft()) {
691 componentsList.add(resourcefetched.left().value());
695 setImports(imports, dependencies, componentsList);
697 setImports(imports, dependencies, fetchedComponent);
703 * Returns all derived_from nodes found.
705 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
706 final Resource parentResource = (Resource) fetchedComponent;
707 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
708 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
709 componentsList.add(fetchedComponent);
710 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
711 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
712 .getToscaElement(componentInstance.getComponentUid());
713 if (resourcefetched != null && resourcefetched.isLeft()) {
714 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
715 if (MapUtils.isNotEmpty(derivedWithId)) {
716 derivedFromMapOfIdToName.putAll(derivedWithId);
721 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
723 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
724 return Optional.ofNullable(derivedFromMapOfIdToName);
728 * Creates a resource map and adds it to the import list.
730 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
731 final Set<Component> componentsList) {
732 componentsList.forEach(component -> setImports(imports, dependencies, component));
735 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
736 final Component component) {
737 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
738 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
739 if (artifactDefinition != null) {
740 final Map<String, String> files = new HashMap<>();
741 final String artifactName = artifactDefinition.getArtifactName();
742 files.put(IMPORTS_FILE_KEY, artifactName);
743 final StringBuilder keyNameBuilder = new StringBuilder();
744 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
745 keyNameBuilder.append("-");
746 keyNameBuilder.append(component.getName());
747 addImports(imports, keyNameBuilder, files);
748 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
749 if (!ModelConverter.isAtomicComponent(component)) {
750 final Map<String, String> interfaceFiles = new HashMap<>();
751 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
752 keyNameBuilder.append("-interface");
753 addImports(imports, keyNameBuilder, interfaceFiles);
759 * Adds the found resource to the import definition list.
761 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
762 final Map<String, String> files) {
763 final String mapKey = keyNameBuilder.toString();
764 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
765 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
766 importsListMember.put(keyNameBuilder.toString(), files);
767 imports.add(importsListMember);
771 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
772 Map<String, ToscaNodeType> nodeTypes) {
773 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
776 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
777 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
778 boolean isAssociatedComponent) {
779 log.debug("start convert node type for {}", component.getUniqueId());
780 ToscaNodeType toscaNodeType = createNodeType(component);
781 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
782 .getAllInterfaceLifecycleTypes(component.getModel());
783 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
784 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
785 return Either.right(ToscaError.GENERAL_ERROR);
787 if (lifecycleTypeEither.isLeft()) {
788 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
789 .collect(Collectors.toList());
790 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
792 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
793 if (dataTypesEither.isRight()) {
794 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
795 return Either.right(ToscaError.GENERAL_ERROR);
797 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
798 List<InputDefinition> inputDef = component.getInputs();
799 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
800 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
801 if (!toscaAttributeMap.isEmpty()) {
802 toscaNodeType.setAttributes(toscaAttributeMap);
804 final var mergedProperties = convertInputsToProperties(dataTypes, inputDef, component.getUniqueId());
805 if (CollectionUtils.isNotEmpty(component.getProperties())) {
806 List<PropertyDefinition> properties = component.getProperties();
807 Map<String, ToscaProperty> convertedProperties = properties.stream()
808 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
809 .toMap(PropertyDataDefinition::getName,
810 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
811 // merge component properties and inputs properties
812 mergedProperties.putAll(convertedProperties);
814 if (MapUtils.isNotEmpty(mergedProperties)) {
815 toscaNodeType.setProperties(mergedProperties);
817 /* convert private data_types */
818 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
819 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
820 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
821 for (DataTypeDefinition dataType : privateDataTypes) {
822 log.debug("Emitting private data type: component.name={} dataType.name={}",
823 component.getNormalizedName(), dataType.getName());
824 ToscaDataType toscaDataType = new ToscaDataType();
825 toscaDataType.setDerived_from(dataType.getDerivedFromName());
826 toscaDataType.setDescription(dataType.getDescription());
827 toscaDataType.setVersion(dataType.getVersion());
828 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
829 toscaDataType.setProperties(dataType.getProperties().stream()
830 .collect(Collectors.toMap(
831 PropertyDataDefinition::getName,
832 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
833 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
837 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
839 toscaNode.setData_types(toscaDataTypeMap);
842 // Extracted to method for code reuse
843 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
846 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
847 final ToscaProperty toscaProperty) {
848 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
849 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
850 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
853 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
854 final Map<String, DataTypeDefinition> dataTypes) {
855 if (CollectionUtils.isEmpty(attributeList)) {
856 return Collections.emptyMap();
858 final AttributeConverter converter = new AttributeConverter(dataTypes);
859 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
860 for (final AttributeDefinition attributeDefinition : attributeList) {
861 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
863 return toscaAttributeMap;
866 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
867 Component component, ToscaTemplate toscaNode,
868 Map<String, ToscaNodeType> nodeTypes,
869 ToscaNodeType toscaNodeType,
870 Map<String, DataTypeDefinition> dataTypes) {
871 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
873 if (capabilities.isRight()) {
874 return Either.right(capabilities.right().value());
876 toscaNodeType = capabilities.left().value();
877 log.debug("Capabilities converted for {}", component.getUniqueId());
879 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
880 .convertRequirements(componentsCache, component, toscaNodeType);
881 if (requirements.isRight()) {
882 return Either.right(requirements.right().value());
884 toscaNodeType = requirements.left().value();
885 log.debug("Requirements converted for {}", component.getUniqueId());
887 String toscaResourceName;
888 switch (component.getComponentType()) {
890 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
891 .getMetadataDataDefinition()).getToscaResourceName();
894 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
895 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
898 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
899 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
902 nodeTypes.put(toscaResourceName, toscaNodeType);
903 toscaNode.setNode_types(nodeTypes);
904 log.debug("finish convert node type for {}", component.getUniqueId());
905 return Either.left(toscaNode);
908 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
909 final Map<String, Component> componentCache,
910 final Map<String, DataTypeDefinition> dataTypes,
911 final ToscaTopolgyTemplate topologyTemplate) {
913 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
914 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
915 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
916 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
917 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
919 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
920 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
921 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
923 Map<String, ToscaGroupTemplate> groupsMap = null;
924 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
925 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
926 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
927 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
929 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
930 List<Object> occur = new ArrayList<>();
931 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
932 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
933 nodeTemplate.setOccurrences(occur);
935 if (componentInstance.getInstanceCount() != null) {
936 ObjectMapper objectMapper = new ObjectMapper();
937 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
939 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
940 nodeTemplate.setInstance_count(map);
943 nodeTemplate.setType(componentInstance.getToscaComponentName());
944 nodeTemplate.setDirectives(componentInstance.getDirectives());
945 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
946 if(nodeFilter != null && nodeFilter.hasData()){
947 nodeTemplate.setNode_filter(nodeFilter);
949 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
950 .getOriginComponent(componentCache, componentInstance);
951 if (originComponentRes.isRight()) {
952 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
955 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
956 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
957 if (requirements.isRight()) {
958 convertNodeTemplatesRes = Either.right(requirements.right().value());
961 final String instanceUniqueId = componentInstance.getUniqueId();
962 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
964 nodeTemplate = requirements.left().value();
966 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
968 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
969 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
970 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
972 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
975 final Either<ToscaNodeTemplate, ToscaError> capabilities =
976 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
977 if (capabilities.isRight()) {
978 convertNodeTemplatesRes = Either.right(capabilities.right().value());
981 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
983 nodeTemplate = capabilities.left().value();
984 final Map<String, Object> props = new HashMap<>();
985 final Map<String, Object> attribs = new HashMap<>();
987 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
988 // Adds the properties of parent component to map
989 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
990 addAttributesOfParentComponent(originalComponent, attribs);
993 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
994 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
996 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
997 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1000 if (componentInstancesInputs != null
1001 && componentInstancesInputs.containsKey(instanceUniqueId)
1002 && !isComponentOfTypeServiceProxy(componentInstance)) {
1003 //For service proxy the inputs are already handled under instance properties above
1004 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1007 //M3[00001] - NODE TEMPLATE INTERFACES - START
1008 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1009 //M3[00001] - NODE TEMPLATE INTERFACES - END
1010 if (MapUtils.isNotEmpty(props)) {
1011 nodeTemplate.setProperties(props);
1013 if (MapUtils.isNotEmpty(attribs)) {
1014 nodeTemplate.setAttributes(attribs);
1017 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1018 if (CollectionUtils.isNotEmpty(groupInstances)) {
1019 if (groupsMap == null) {
1020 groupsMap = new HashMap<>();
1022 for (final GroupInstance groupInst : groupInstances) {
1023 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1024 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1029 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1031 if (groupsMap != null) {
1032 log.debug("instance groups added");
1033 topologyTemplate.addGroups(groupsMap);
1035 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1036 ((Service) component).getForwardingPaths())) {
1037 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1038 ForwardingPathToscaUtil
1039 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1040 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1042 if (convertNodeTemplatesRes == null) {
1043 convertNodeTemplatesRes = Either.left(nodeTemplates);
1045 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1046 return convertNodeTemplatesRes;
1049 private Object convertToToscaObject(String value) {
1051 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1052 StringReader reader = new StringReader(value);
1053 JsonReader jsonReader = new JsonReader(reader);
1054 jsonReader.setLenient(true);
1055 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1056 if (jsonElement.isJsonObject()) {
1057 JsonObject jsonObj = jsonElement.getAsJsonObject();
1058 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1059 return mapConverterInst.handleComplexJsonValue(jsonElement);
1063 } catch (Exception e) {
1064 log.debug("convertToToscaValue failed to parse json value :", e);
1069 private Object parseToIntIfPossible(final String value) {
1070 final Integer intValue = Ints.tryParse(value);
1071 return intValue == null ? value : intValue;
1074 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1075 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1076 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1078 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1079 nodeTemplate.setInterfaces(null);
1083 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1085 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1086 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1088 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1089 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1091 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1092 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1095 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1096 return Objects.nonNull(componentInstance.getOriginType())
1097 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1100 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1101 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1102 String instanceUniqueId, Map<String, Object> props) {
1104 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1105 if (instanceInputsList != null) {
1106 instanceInputsList.forEach(input -> {
1107 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1108 : input.getDefaultValue();
1109 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1114 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1115 final Map<String, DataTypeDefinition> dataTypes,
1116 final String instanceUniqueId,
1117 final Map<String, Object> props) {
1119 if (isNotEmpty(componentInstancesProperties)) {
1120 componentInstancesProperties.get(instanceUniqueId)
1121 // Converts and adds each value to property map
1122 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1126 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1127 final String instanceUniqueId,
1128 final Map<String, Object> attribs) {
1130 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1131 componentInstancesAttributes.get(instanceUniqueId)
1132 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1136 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1137 Component componentOfInstance, Map<String, Object> props) {
1139 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1140 if (isNotEmpty(componentProperties)) {
1141 componentProperties.stream()
1142 // Filters out properties with empty default values
1143 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1144 // Converts and adds each value to property map
1145 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1149 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1151 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1152 if (isNotEmpty(componentAttributes)) {
1153 componentAttributes.stream()
1154 // Filters out Attributes with empty default values
1155 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1156 // Converts and adds each value to attribute map
1157 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1161 private ToscaNodeType createNodeType(Component component) {
1162 ToscaNodeType toscaNodeType = new ToscaNodeType();
1163 if (ModelConverter.isAtomicComponent(component)) {
1164 if (((Resource) component).getDerivedFrom() != null) {
1165 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1167 toscaNodeType.setDescription(component.getDescription());
1169 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1171 toscaNodeType.setDerived_from(derivedFrom);
1173 return toscaNodeType;
1176 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1178 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1179 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1180 List<ComponentInstance> componentInstances = container.getComponentInstances();
1181 if (CollectionUtils.isEmpty(componentInstances)) {
1184 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1185 componentInstances.stream()
1186 .filter(this::isComponentOfTypeServiceProxy)
1187 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1188 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1191 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1192 Component serviceComponent;
1193 ComponentParametersView componentParametersView = new ComponentParametersView();
1194 componentParametersView.disableAll();
1195 componentParametersView.setIgnoreInterfaces(false);
1196 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1197 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1198 if (service.isRight()) {
1199 log.debug("Failed to fetch original service component with id {} for instance {}",
1200 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1201 return Either.right(ToscaError.GENERAL_ERROR);
1203 serviceComponent = service.left().value();
1206 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1207 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1208 if (lifecycleTypeEither.isRight()) {
1209 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1210 return Either.right(ToscaError.GENERAL_ERROR);
1213 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1214 .map(InterfaceDataDefinition::getType)
1215 .collect(Collectors.toList());
1216 //Add interface types for local interfaces in the original service component for proxy
1217 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1218 allGlobalInterfaceTypes);
1219 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1220 proxyInterfaceTypes.putAll(localInterfaceTypes);
1224 return Either.left(proxyInterfaceTypes);
1227 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1228 Component container) {
1230 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1231 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1233 List<ComponentInstance> componentInstances = container.getComponentInstances();
1235 if (componentInstances == null || componentInstances.isEmpty()) {
1238 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1239 List<ComponentInstance> proxyInst = componentInstances.stream()
1240 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1241 .collect(Collectors.toList());
1242 if (proxyInst != null && !proxyInst.isEmpty()) {
1243 for (ComponentInstance inst : proxyInst) {
1244 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1248 if (serviceProxyInstanceList.isEmpty()) {
1251 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1252 .getLatestByName("serviceProxy", null);
1253 if (serviceProxyOrigin.isRight()) {
1254 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1255 serviceProxyOrigin.right().value());
1256 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1258 Component origComponent = serviceProxyOrigin.left().value();
1260 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1261 Component serviceComponent = null;
1262 ComponentParametersView componentParametersView = new ComponentParametersView();
1263 componentParametersView.disableAll();
1264 componentParametersView.setIgnoreCategories(false);
1265 componentParametersView.setIgnoreProperties(false);
1266 componentParametersView.setIgnoreInputs(false);
1267 componentParametersView.setIgnoreInterfaces(false);
1268 componentParametersView.setIgnoreRequirements(false);
1269 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1270 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1271 if (service.isRight()) {
1272 log.debug("Failed to fetch resource with id {} for instance {}",
1273 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1275 serviceComponent = service.left().value();
1278 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1279 entryProxy.getValue());
1280 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1283 return Either.left(nodeTypesMap);
1286 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1287 final Component container, final ToscaTemplate toscaNode) {
1288 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1290 if (CollectionUtils.isEmpty(componentInstances)) {
1293 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1294 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1295 .collect(Collectors.toList());
1296 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1297 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1298 final Map<String, ToscaNodeType> nodeTypes =
1299 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1300 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1306 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1307 Component proxyComponent, ComponentInstance componentInstance) {
1308 ToscaNodeType toscaNodeType = new ToscaNodeType();
1309 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1311 toscaNodeType.setDerived_from(derivedFrom);
1312 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1313 origComponent.getModel());
1314 if (dataTypesEither.isRight()) {
1315 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1317 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1318 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1319 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1321 if (MapUtils.isNotEmpty(capabilities)) {
1322 toscaNodeType.setCapabilities(capabilities);
1324 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1325 .convertProxyRequirements(componentCache, componentInstance);
1326 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1327 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1329 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1330 proxyProperties.ifPresent(toscaNodeType::setProperties);
1332 Map<String, Object> interfaceMap = new HashMap<>();
1333 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1334 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1335 if (proxyInterfaces.isPresent()) {
1336 interfaceMap = proxyInterfaces.get();
1339 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1342 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1343 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1345 return toscaNodeType;
1348 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1349 ComponentInstance componentInstance,
1350 List<RequirementCapabilityRelDef> relations,
1351 ToscaNodeTemplate nodeTypeTemplate,
1352 Component originComponent,
1353 Map<String, Component> componentCache) {
1355 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1357 if (isNotEmpty(requirementDefinitionList)) {
1359 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1360 requirementDefinitionList, originComponent, componentCache);
1361 if (!toscaRequirements.isEmpty()) {
1362 nodeTypeTemplate.setRequirements(toscaRequirements);
1364 } catch (final Exception e) {
1365 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1366 componentInstance.getName(), e);
1367 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1370 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1371 return Either.left(nodeTypeTemplate);
1374 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1375 final ComponentInstance componentInstance,
1376 final List<RequirementCapabilityRelDef> filteredRelations,
1377 final Component originComponent,
1378 final Map<String, Component> componentCache)
1379 throws ToscaExportException {
1381 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1382 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1383 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1384 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1385 toscaRequirements.add(toscaTemplateRequirementMap);
1388 return toscaRequirements;
1391 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1392 List<RequirementCapabilityRelDef> relations) {
1393 return relations.stream()
1394 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1397 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1398 final Component fromOriginComponent,
1399 final List<ComponentInstance> instancesList,
1400 final RequirementCapabilityRelDef relationshipDefinition,
1401 final Map<String, Component> componentCache)
1402 throws ToscaExportException {
1404 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1405 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1406 .getRelationships().get(0);
1407 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1409 final ComponentInstance toInstance = instancesList.stream()
1410 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1411 .findFirst().orElse(null);
1412 if (toInstance == null) {
1413 final String errorMsg = String
1414 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1415 relationshipDefinition.getToNode());
1416 log.debug(errorMsg);
1417 throw new ToscaExportException(errorMsg);
1419 final Optional<RequirementDefinition> reqOpt =
1420 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1421 if (reqOpt.isEmpty()) {
1422 final String errorMsg = String
1423 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1424 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1425 log.debug(errorMsg);
1426 throw new ToscaExportException(errorMsg);
1428 final ComponentParametersView filter = new ComponentParametersView(true);
1429 filter.setIgnoreComponentInstances(false);
1430 filter.setIgnoreCapabilities(false);
1431 filter.setIgnoreGroups(false);
1432 final Either<Component, StorageOperationStatus> getOriginRes =
1433 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1434 if (getOriginRes.isRight()) {
1435 final String errorMsg = String.format(
1436 "Failed to build substituted name for the requirement %s. "
1437 + "Failed to get an origin component with uniqueId %s",
1438 reqOpt.get().getName(), toInstance.getActualComponentUid());
1439 log.debug(errorMsg);
1440 throw new ToscaExportException(errorMsg);
1442 final Component toOriginComponent = getOriginRes.left().value();
1443 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1444 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1445 if (capOpt.isEmpty()) {
1446 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1447 if (capOpt.isEmpty()) {
1448 final String errorMsg = String
1449 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1450 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1451 log.debug(errorMsg);
1452 throw new ToscaExportException(errorMsg);
1455 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1456 capabilityRequirementRelationship, toInstance, componentCache);
1459 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1460 CapabilityDefinition capability) {
1461 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1462 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1465 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1466 Component toOriginComponent, Component fromOriginComponent,
1467 RequirementDefinition requirement) {
1468 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1469 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1470 if (!cap.isPresent()) {
1471 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1472 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1477 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1478 final Component toOriginComponent,
1479 final CapabilityDefinition capability,
1480 final RequirementDefinition requirement,
1481 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1482 final ComponentInstance toInstance,
1483 final Map<String, Component> componentCache)
1484 throws ToscaExportException {
1486 List<String> reducedPath = capability.getPath();
1487 if (capability.getOwnerId() != null) {
1488 reducedPath = capabilityRequirementConverter
1489 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1491 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1492 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1493 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1494 if (capabilityNameEither.isRight()) {
1495 final String errorMsg = String.format(
1496 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1497 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1500 throw new ToscaExportException(errorMsg);
1502 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1503 .buildSubstitutedName(componentCache, fromOriginComponent,
1504 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1505 if (requirementNameEither.isRight()) {
1506 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1507 + "with name %s on a component with uniqueId %s",
1508 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1509 log.debug(errorMsg);
1510 throw new ToscaExportException(errorMsg);
1512 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1513 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1514 toscaRequirement.setNode(toInstance.getName());
1515 toscaRequirement.setCapability(capabilityNameEither.left().value());
1516 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1517 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1519 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1523 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1524 Map<String, List<RequirementDefinition>> reqMap,
1525 RelationshipInfo reqAndRelationshipPair,
1526 String fromInstanceId) {
1527 for (List<RequirementDefinition> reqList : reqMap.values()) {
1528 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1529 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1531 if (reqOpt.isPresent()) {
1535 return Optional.empty();
1539 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1540 * 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
1541 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1543 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1544 RequirementDefinition requirement, String fromInstanceId) {
1545 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1546 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1547 reqAndRelationshipPair.getRequirement());
1550 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1554 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1555 Component originComponent) {
1556 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1557 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1558 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1561 private boolean isCvfc(Component component) {
1562 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1565 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1566 final Map<String, Component> componentCache) {
1567 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1568 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1569 if (toscaCapabilitiesRes.isRight()) {
1570 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1571 return Either.right(toscaCapabilitiesRes.right().value());
1573 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1574 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1575 return Either.left(toscaCapabilitiesRes.left().value());
1577 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1579 return Either.left(Collections.emptyMap());
1582 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1583 Map<String, DataTypeDefinition> dataTypes) {
1584 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1585 if (!toscaCapabilities.isEmpty()) {
1586 nodeType.setCapabilities(toscaCapabilities);
1588 log.debug("Finish convert Capabilities for node type");
1589 return Either.left(nodeType);
1592 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1593 if (artifacts == null) {
1596 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1597 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1598 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1599 artifact.setFile(entry.getValue().getFile());
1600 artifact.setType(entry.getValue().getType());
1601 artifact.setProperties(entry.getValue().getProperties());
1602 arts.put(entry.getKey(), artifact);
1607 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1608 if (inNodeFilter == null) {
1611 NodeFilter nodeFilter = new NodeFilter();
1612 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1613 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1614 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1615 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1616 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1617 nodeFilter.setCapabilities(capabilitiesCopy);
1619 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1620 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1621 nodeFilter.setProperties(propertiesCopy);
1623 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1624 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1628 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1629 if (substitutionFilterDataDefinition == null) {
1632 NodeFilter nodeFilter = new NodeFilter();
1633 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1634 if (!propertiesCopy.isEmpty()) {
1635 nodeFilter.setProperties(propertiesCopy);
1637 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1638 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1641 private Object cloneToscaId(Object toscaId) {
1642 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1645 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1646 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1647 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1650 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1651 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1652 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1656 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1657 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1658 final var capabilityFilter = new CapabilityFilter();
1659 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1660 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1661 capabilitiesCopy.add(capabilityFilterCopyMap);
1665 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1666 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1667 return Collections.emptyList();
1669 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1670 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1671 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1672 final String propertyName = propertyFilter.getName();
1673 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1674 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1675 if (constraints == null) {
1676 constraints = new ArrayList<>();
1678 constraints.add(buildNodeFilterValue(filterConstraint));
1683 propertyFilterDefinitionMap.entrySet().stream()
1684 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1685 .forEach(propertiesCopy::add);
1686 return propertiesCopy;
1689 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1690 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1692 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1693 return Collections.emptyList();
1695 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1696 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1697 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1698 final String propertyName = propertyFilter.getName();
1699 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1700 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1701 if (constraints == null) {
1702 constraints = new ArrayList<>();
1704 constraints.add(buildNodeFilterValue(filterConstraint));
1709 propertyFilterDefinitionMap.entrySet().stream()
1710 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1711 .forEach(propertiesCopy::add);
1712 return propertiesCopy;
1715 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1716 if (filterConstraint.getValue() instanceof ToscaFunction) {
1717 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1719 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1723 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1724 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1725 return Collections.emptyMap();
1727 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1728 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1731 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1732 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1733 return Collections.emptyMap();
1735 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1736 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1739 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1740 if (Objects.isNull(proxyComponent)) {
1741 return Optional.empty();
1743 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1744 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1745 proxyProperties.putAll(proxyComponent.getProperties().stream()
1746 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1747 .toMap(PropertyDataDefinition::getName,
1748 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1750 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1753 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1754 String componentUniqueId) {
1755 if (CollectionUtils.isEmpty(componentInputs)) {
1756 return new HashMap<>();
1758 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1759 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1762 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1763 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1764 return Optional.empty();
1766 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1767 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1769 // always available in the proxy node template
1770 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1771 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1774 private static class CustomRepresenter extends Representer {
1776 CustomRepresenter() {
1778 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1779 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1780 // null representer is exceptional and it is stored as an instance
1783 this.nullRepresenter = new RepresentNull();
1786 public boolean validateGetInputValue(final Object valueObj) {
1787 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1790 if (valueObj instanceof List) {
1791 return ((List) valueObj).size() > 1;
1796 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1797 if (valueObj instanceof List) {
1798 return ((List) valueObj).size() > 1;
1804 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1805 if (propertyValue == null) {
1808 // skip not relevant for Tosca property
1809 if ("dependencies".equals(property.getName())) {
1812 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1815 if (javaBean instanceof ToscaPropertyConstraint) {
1816 return handleToscaPropertyConstraint((ToscaPropertyConstraint)javaBean, property, propertyValue, customTag);
1818 removeDefaultP(propertyValue);
1819 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1820 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1821 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1823 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1826 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1827 final Tag customTag) {
1828 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1829 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1830 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1833 private void removeDefaultP(final Object propertyValue) {
1834 if (propertyValue instanceof Map) {
1835 final Map mapPropertyValue = ((Map) propertyValue);
1836 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1837 Object defaultValue = null;
1838 while (iter.hasNext()) {
1839 final Map.Entry entry = iter.next();
1840 if ("_defaultp_".equals(entry.getKey())) {
1841 defaultValue = entry.getValue();
1843 } else if (entry.getValue() instanceof Map) {
1844 removeDefaultP(entry.getValue());
1847 if (defaultValue != null) {
1848 mapPropertyValue.putIfAbsent("default", defaultValue);
1854 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1855 // remove the bean type from the output yaml (!! ...)
1856 if (!classTags.containsKey(javaBean.getClass())) {
1857 addClassTag(javaBean.getClass(), Tag.MAP);
1859 return super.representJavaBean(properties, javaBean);
1862 private class RepresentToscaAttribute implements Represent {
1865 public Node representData(Object data) {
1866 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1867 return represent(toscaAttribute.asToscaMap());
1871 private class RepresentToscaPropertyAssignment implements Represent {
1873 public Node representData(Object data) {
1874 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1875 if (toscaOperationAssignment.getValue() instanceof String) {
1876 final String stringValue = (String) toscaOperationAssignment.getValue();
1877 if (isPropertyOrAttributeFunction(stringValue)) {
1878 return representGetAttribute(stringValue);
1880 return representScalar(Tag.STR, stringValue);
1882 return represent(null);
1885 public Node representGetAttribute(final String getAttributeFunction) {
1886 return represent(new Yaml().load(getAttributeFunction));
1889 public boolean isPropertyOrAttributeFunction(final String value) {
1891 final Yaml yaml = new Yaml();
1892 final Object yamlObj = yaml.load(value);
1893 if (!(yamlObj instanceof Map)) {
1896 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1897 if (getAttributeMap.size() != 1) {
1900 final List<String> functionList = Arrays
1901 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1902 final Optional<String> function = getAttributeMap.keySet().stream()
1903 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1904 if (function.isEmpty()) {
1907 final String functionName = function.get();
1908 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1909 if (GET_INPUT.getFunctionName().equals(functionName)) {
1910 return validateGetInputValue(getAttributeValueObj);
1912 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1914 } catch (final Exception ignored) {
1920 private class RepresentNull implements Represent {
1923 public Node representData(Object data) {
1924 // possible values are here http://yaml.org/type/null.html
1925 return representScalar(Tag.NULL, "");
1930 private static class UnsortedPropertyUtils extends PropertyUtils {
1933 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1934 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1935 return new LinkedHashSet<>(fields);
1939 private Configuration getConfiguration() {
1940 return ConfigurationManager.getConfigurationManager().getConfiguration();