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> exportDataType(DataTypeDefinition dataTypeDefinition) {
230 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
233 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
234 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
235 if (CollectionUtils.isEmpty(imports)) {
236 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
237 return Either.right(ToscaError.GENERAL_ERROR);
239 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
240 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
241 .startsWith("org.openecomp.resource.abstract.nodes.")) {
242 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
243 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
244 component.getModel());
245 if (baseType.isLeft() && baseType.left().value() != null) {
246 addDependencies(imports, dependencies, baseType.left().value());
248 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
252 String toscaVersion = null;
253 if (component instanceof Resource) {
254 toscaVersion = ((Resource) component).getToscaVersion();
256 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
257 toscaTemplate.setImports(imports);
258 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
259 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
260 isAssociatedComponent);
261 if (toscaTemplateRes.isRight()) {
262 return Either.right(toscaTemplateRes.right().value());
264 toscaTemplate = toscaTemplateRes.left().value();
265 toscaTemplate.setDependencies(dependencies);
266 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
267 return Either.left(toscaRepresentation);
270 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
271 CustomRepresenter representer = new CustomRepresenter();
272 DumperOptions options = new DumperOptions();
273 options.setAllowReadOnlyProperties(false);
274 options.setPrettyFlow(true);
275 options.setDefaultFlowStyle(FlowStyle.FLOW);
276 options.setCanonical(false);
277 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
278 representer.setPropertyUtils(new UnsortedPropertyUtils());
281 Yaml yaml = new Yaml(representer, options);
282 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
283 StringBuilder sb = new StringBuilder();
284 sb.append(getConfiguration().getHeatEnvArtifactHeader());
285 sb.append(yamlAsString);
286 sb.append(getConfiguration().getHeatEnvArtifactFooter());
287 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
290 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
291 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
292 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
293 if (fillImports.isRight()) {
294 return Either.right(fillImports.right().value());
296 return Either.left(fillImports.left().value().left);
299 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
300 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
301 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
302 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
303 return Either.right(ToscaError.GENERAL_ERROR);
305 log.trace("start tosca export for {}", component.getUniqueId());
306 String toscaVersion = null;
307 if (component instanceof Resource) {
308 toscaVersion = ((Resource) component).getToscaVersion();
310 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
311 toscaTemplate.setMetadata(convertMetadata(component));
312 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
313 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
314 if (ModelConverter.isAtomicComponent(component)) {
315 log.trace("convert component as node type");
316 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
318 log.trace("convert component as topology template");
319 return convertToscaTemplate(component, toscaTemplate);
323 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
324 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
325 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
328 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
329 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
330 if (dataTypesEither.isRight()) {
331 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
332 return Either.right(ToscaError.GENERAL_ERROR);
334 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
335 if (!dataTypeDefinition.isEmpty()) {
336 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
337 ToscaDataType toscaDataType = new ToscaDataType();
338 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
339 toscaDataType.setDescription(dataTypeDefinition.getDescription());
340 toscaDataType.setVersion(dataTypeDefinition.getVersion());
341 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
342 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
343 .collect(Collectors.toMap(
344 PropertyDataDefinition::getName,
345 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
346 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition, toscaPropertyTobeValidated,
350 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
351 toscaTemplate.setData_types(toscaDataTypeMap);
353 return Either.left(toscaTemplate);
356 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
357 if (modelId == null) {
358 return getDefaultToscaImportConfig();
361 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
362 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
363 final Set<Path> addedPathList = new HashSet<>();
364 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
365 var importPath = Path.of(toscaImportByModel.getFullPath());
366 if (addedPathList.contains(importPath)) {
367 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
369 final String fileName = FilenameUtils.getBaseName(importPath.toString());
370 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
371 addedPathList.add(importPath);
376 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
377 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
378 if (importsRes.isRight()) {
379 return Either.right(importsRes.right().value());
381 toscaNode = importsRes.left().value().left;
382 Map<String, Component> componentCache = importsRes.left().value().right;
383 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
384 if (nodeTypesMapEither.isRight()) {
385 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
386 return Either.right(nodeTypesMapEither.right().value());
388 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
389 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
390 toscaNode.setNode_types(nodeTypesMap);
392 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
393 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
394 if (proxyInterfaceTypesEither.isRight()) {
395 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
396 return Either.right(proxyInterfaceTypesEither.right().value());
398 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
399 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
400 toscaNode.setInterface_types(proxyInterfaceTypes);
402 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
403 if (dataTypesEither.isRight()) {
404 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
405 return Either.right(ToscaError.GENERAL_ERROR);
407 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
408 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
409 List<InputDefinition> inputDef = component.getInputs();
410 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
411 if (!inputs.isEmpty()) {
412 topologyTemplate.setInputs(inputs);
414 final Map<String, ToscaProperty> outputs;
416 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
417 } catch (final ToscaConversionException e) {
418 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
419 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
420 return Either.right(ToscaError.GENERAL_ERROR);
422 if (!outputs.isEmpty()) {
423 topologyTemplate.setOutputs(outputs);
425 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
426 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
427 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
428 if (nodeTemplates.isRight()) {
429 return Either.right(nodeTemplates.right().value());
431 log.debug("node templates converted");
432 topologyTemplate.setNode_templates(nodeTemplates.left().value());
434 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
435 .createFrom(topologyTemplate.getNode_templates());
436 if (!relationshipTemplatesMap.isEmpty()) {
437 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
439 addGroupsToTopologyTemplate(component, topologyTemplate);
441 addPoliciesToTopologyTemplate(component, topologyTemplate);
442 } catch (SdcResourceNotFoundException e) {
443 log.debug("Fail to add policies to topology template:", e);
444 return Either.right(ToscaError.GENERAL_ERROR);
447 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
448 } catch (final ToscaExportException e) {
449 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
450 return Either.right(e.getToscaError());
452 if (!topologyTemplate.isEmpty()) {
453 toscaNode.setTopology_template(topologyTemplate);
455 return Either.left(toscaNode);
458 private Either<String, ToscaError> createComponentToscaName(final Component component) {
459 switch (component.getComponentType()) {
461 final ResourceMetadataDataDefinition resourceMetadata =
462 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
463 return Either.left(resourceMetadata.getToscaResourceName());
465 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
467 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
468 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
472 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
473 final Map<String, Component> componentCache) throws ToscaExportException {
474 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
475 return Optional.empty();
478 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
479 if (toscaResourceNameEither.isRight()) {
480 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
482 final String toscaResourceName = toscaResourceNameEither.left().value();
484 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
485 substitutionMapping.setNode_type(toscaResourceName);
486 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
488 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
489 if (capabilitiesEither.isRight()) {
490 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
492 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
493 if (!capabilityMap.isEmpty()) {
494 substitutionMapping.setCapabilities(capabilityMap);
497 final Either<Map<String, String[]>, ToscaError> requirements =
498 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
499 if (requirements.isRight()) {
500 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
502 final Map<String, String[]> requirementMap = requirements.left().value();
503 if (MapUtils.isNotEmpty(requirementMap)) {
504 substitutionMapping.setRequirements(requirementMap);
507 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
508 if (MapUtils.isNotEmpty(propertyMappingMap)) {
509 substitutionMapping.setProperties(propertyMappingMap);
512 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
513 if (MapUtils.isNotEmpty(attributesMappingMap)) {
514 substitutionMapping.setAttributes(attributesMappingMap);
517 return Optional.of(substitutionMapping);
520 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
521 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
522 return Optional.empty();
525 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
528 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
529 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
530 if (groups != null) {
531 topologyTemplate.addGroups(groups);
535 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
536 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
537 if (policies != null) {
538 topologyTemplate.addPolicies(policies);
542 private Map<String, String> convertMetadata(Component component) {
543 return convertMetadata(component, false, null);
546 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
547 Map<String, String> toscaMetadata = new LinkedHashMap<>();
548 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
549 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
551 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
552 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
553 List<CategoryDefinition> categories = component.getCategories();
554 CategoryDefinition categoryDefinition = categories.get(0);
555 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
556 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
558 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
559 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
560 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
561 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
562 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
563 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
564 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
565 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
566 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
567 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
568 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
569 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
570 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
572 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
575 switch (component.getComponentType()) {
577 Resource resource = (Resource) component;
578 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
579 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
580 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
582 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
584 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
585 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
586 if (resource.getTenant() != null) {
587 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
589 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
590 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
593 Service service = (Service) component;
594 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
595 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
596 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
597 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
598 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
599 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
600 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
603 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
604 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
605 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
609 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
611 for (final String key : component.getCategorySpecificMetadata().keySet()) {
612 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
613 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
616 return toscaMetadata;
619 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
620 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
621 return INVARIANT_UUID;
623 return jsonPresentationField.getPresentation();
626 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
627 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
628 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
629 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
630 return Either.right(ToscaError.GENERAL_ERROR);
632 Map<String, Component> componentCache = new HashMap<>();
633 if (!ModelConverter.isAtomicComponent(component)) {
634 final List<Map<String, Map<String, String>>> additionalImports =
635 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
636 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
637 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
638 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
639 if (!substituteTypeImportEntry.isEmpty()) {
640 additionalImports.add(substituteTypeImportEntry);
642 List<ComponentInstance> componentInstances = component.getComponentInstances();
643 if (componentInstances != null && !componentInstances.isEmpty()) {
644 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
646 toscaTemplate.setDependencies(dependencies);
647 toscaTemplate.setImports(additionalImports);
649 log.debug("currently imports supported for VF and service only");
651 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
654 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
655 final Map<String, ArtifactDefinition> toscaArtifacts) {
657 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
658 return Collections.emptyMap();
660 if (MapUtils.isEmpty(toscaArtifacts)) {
661 return Collections.emptyMap();
663 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
664 if (artifactDefinition == null) {
665 return Collections.emptyMap();
667 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
668 return Map.of(importEntryName,
669 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
673 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
674 return getConfiguration().getDefaultImports();
677 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
678 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
679 log.debug("createDependency componentCache {}", componentCache);
680 Component componentRI = componentCache.get(componentInstance.getComponentUid());
681 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
682 // all resource must be only once!
683 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
684 if ((resource.isRight()) && (log.isDebugEnabled())) {
685 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
686 componentInstance.getUniqueId());
689 final Component fetchedComponent = resource.left().value();
690 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
691 addDependencies(imports, dependencies, componentRI);
696 * Sets a componentCache from the given component/resource.
698 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
699 final Component fetchedComponent) {
700 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
701 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
702 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
703 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
704 .getToscaFullElement(componentInstance.getSourceModelUid());
705 if (sourceService.isRight() && (log.isDebugEnabled())) {
706 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
707 componentInstance.getUniqueId());
709 final Component fetchedSource = sourceService.left().value();
710 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
711 return fetchedSource;
713 return fetchedComponent;
717 * Retrieves all derived_from nodes and stores it in a predictable order.
719 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
720 final Component fetchedComponent) {
721 final Set<Component> componentsList = new LinkedHashSet<>();
722 if (fetchedComponent instanceof Resource) {
723 log.debug("fetchedComponent is a resource {}", fetchedComponent);
724 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
725 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
726 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
727 log.debug("Started entry.getValue() : {}", entry.getValue());
728 if (!NATIVE_ROOT.equals(entry.getValue())) {
729 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
730 if (resourcefetched != null && resourcefetched.isLeft()) {
731 componentsList.add(resourcefetched.left().value());
735 setImports(imports, dependencies, componentsList);
737 setImports(imports, dependencies, fetchedComponent);
743 * Returns all derived_from nodes found.
745 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
746 final Resource parentResource = (Resource) fetchedComponent;
747 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
748 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
749 componentsList.add(fetchedComponent);
750 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
751 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
752 .getToscaElement(componentInstance.getComponentUid());
753 if (resourcefetched != null && resourcefetched.isLeft()) {
754 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
755 if (MapUtils.isNotEmpty(derivedWithId)) {
756 derivedFromMapOfIdToName.putAll(derivedWithId);
761 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
763 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
764 return Optional.ofNullable(derivedFromMapOfIdToName);
768 * Creates a resource map and adds it to the import list.
770 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
771 final Set<Component> componentsList) {
772 componentsList.forEach(component -> setImports(imports, dependencies, component));
775 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
776 final Component component) {
777 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
778 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
779 if (artifactDefinition != null) {
780 final Map<String, String> files = new HashMap<>();
781 final String artifactName = artifactDefinition.getArtifactName();
782 files.put(IMPORTS_FILE_KEY, artifactName);
783 final StringBuilder keyNameBuilder = new StringBuilder();
784 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
785 keyNameBuilder.append("-");
786 keyNameBuilder.append(component.getName());
787 addImports(imports, keyNameBuilder, files);
788 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
789 if (!ModelConverter.isAtomicComponent(component)) {
790 final Map<String, String> interfaceFiles = new HashMap<>();
791 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
792 keyNameBuilder.append("-interface");
793 addImports(imports, keyNameBuilder, interfaceFiles);
799 * Adds the found resource to the import definition list.
801 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
802 final Map<String, String> files) {
803 final String mapKey = keyNameBuilder.toString();
804 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
805 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
806 importsListMember.put(keyNameBuilder.toString(), files);
807 imports.add(importsListMember);
811 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
812 Map<String, ToscaNodeType> nodeTypes) {
813 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
816 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
817 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
818 boolean isAssociatedComponent) {
819 log.debug("start convert node type for {}", component.getUniqueId());
820 ToscaNodeType toscaNodeType = createNodeType(component);
821 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
822 .getAllInterfaceLifecycleTypes(component.getModel());
823 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
824 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
825 return Either.right(ToscaError.GENERAL_ERROR);
827 if (lifecycleTypeEither.isLeft()) {
828 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
829 .collect(Collectors.toList());
830 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
832 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
833 if (dataTypesEither.isRight()) {
834 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
835 return Either.right(ToscaError.GENERAL_ERROR);
837 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
838 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
839 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
840 if (!toscaAttributeMap.isEmpty()) {
841 toscaNodeType.setAttributes(toscaAttributeMap);
843 Map<String, ToscaProperty> convertedProperties = new HashMap();
844 if (CollectionUtils.isNotEmpty(component.getProperties())) {
845 List<PropertyDefinition> properties = component.getProperties();
846 convertedProperties = properties.stream()
847 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
848 .toMap(PropertyDataDefinition::getName,
849 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
851 if (MapUtils.isNotEmpty(convertedProperties)) {
852 toscaNodeType.setProperties(convertedProperties);
854 /* convert private data_types */
855 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
856 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
857 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
858 for (DataTypeDefinition dataType : privateDataTypes) {
859 log.debug("Emitting private data type: component.name={} dataType.name={}",
860 component.getNormalizedName(), dataType.getName());
861 ToscaDataType toscaDataType = new ToscaDataType();
862 toscaDataType.setDerived_from(dataType.getDerivedFromName());
863 toscaDataType.setDescription(dataType.getDescription());
864 toscaDataType.setVersion(dataType.getVersion());
865 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
866 toscaDataType.setProperties(dataType.getProperties().stream()
867 .collect(Collectors.toMap(
868 PropertyDataDefinition::getName,
869 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
870 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
874 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
876 toscaNode.setData_types(toscaDataTypeMap);
879 // Extracted to method for code reuse
880 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
883 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
884 final ToscaProperty toscaProperty) {
885 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
886 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
887 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
890 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
891 final Map<String, DataTypeDefinition> dataTypes) {
892 if (CollectionUtils.isEmpty(attributeList)) {
893 return Collections.emptyMap();
895 final AttributeConverter converter = new AttributeConverter(dataTypes);
896 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
897 for (final AttributeDefinition attributeDefinition : attributeList) {
898 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
900 return toscaAttributeMap;
903 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
904 Component component, ToscaTemplate toscaNode,
905 Map<String, ToscaNodeType> nodeTypes,
906 ToscaNodeType toscaNodeType,
907 Map<String, DataTypeDefinition> dataTypes) {
908 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
910 if (capabilities.isRight()) {
911 return Either.right(capabilities.right().value());
913 toscaNodeType = capabilities.left().value();
914 log.debug("Capabilities converted for {}", component.getUniqueId());
916 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
917 .convertRequirements(componentsCache, component, toscaNodeType);
918 if (requirements.isRight()) {
919 return Either.right(requirements.right().value());
921 toscaNodeType = requirements.left().value();
922 log.debug("Requirements converted for {}", component.getUniqueId());
924 String toscaResourceName;
925 switch (component.getComponentType()) {
927 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
928 .getMetadataDataDefinition()).getToscaResourceName();
931 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
932 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
935 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
936 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
939 nodeTypes.put(toscaResourceName, toscaNodeType);
940 toscaNode.setNode_types(nodeTypes);
941 log.debug("finish convert node type for {}", component.getUniqueId());
942 return Either.left(toscaNode);
945 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
946 final Map<String, Component> componentCache,
947 final Map<String, DataTypeDefinition> dataTypes,
948 final ToscaTopolgyTemplate topologyTemplate) {
950 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
951 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
952 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
953 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
954 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
956 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
957 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
958 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
960 Map<String, ToscaGroupTemplate> groupsMap = null;
961 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
962 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
963 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
964 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
966 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
967 List<Object> occur = new ArrayList<>();
968 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
969 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
970 nodeTemplate.setOccurrences(occur);
972 if (componentInstance.getInstanceCount() != null) {
973 ObjectMapper objectMapper = new ObjectMapper();
974 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
976 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
977 nodeTemplate.setInstance_count(map);
980 nodeTemplate.setType(componentInstance.getToscaComponentName());
981 nodeTemplate.setDirectives(componentInstance.getDirectives());
982 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
983 if(nodeFilter != null && nodeFilter.hasData()){
984 nodeTemplate.setNode_filter(nodeFilter);
986 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
987 .getOriginComponent(componentCache, componentInstance);
988 if (originComponentRes.isRight()) {
989 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
992 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
993 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
994 if (requirements.isRight()) {
995 convertNodeTemplatesRes = Either.right(requirements.right().value());
998 final String instanceUniqueId = componentInstance.getUniqueId();
999 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1001 nodeTemplate = requirements.left().value();
1003 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1005 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1006 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1007 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1009 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1012 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1013 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1014 if (capabilities.isRight()) {
1015 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1018 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1020 nodeTemplate = capabilities.left().value();
1021 final Map<String, Object> props = new HashMap<>();
1022 final Map<String, Object> attribs = new HashMap<>();
1024 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1025 // Adds the properties of parent component to map
1026 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1027 addAttributesOfParentComponent(originalComponent, attribs);
1030 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1031 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1033 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1034 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1037 if (componentInstancesInputs != null
1038 && componentInstancesInputs.containsKey(instanceUniqueId)
1039 && !isComponentOfTypeServiceProxy(componentInstance)) {
1040 //For service proxy the inputs are already handled under instance properties above
1041 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1044 //M3[00001] - NODE TEMPLATE INTERFACES - START
1045 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1046 //M3[00001] - NODE TEMPLATE INTERFACES - END
1047 if (MapUtils.isNotEmpty(props)) {
1048 nodeTemplate.setProperties(props);
1050 if (MapUtils.isNotEmpty(attribs)) {
1051 nodeTemplate.setAttributes(attribs);
1054 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1055 if (CollectionUtils.isNotEmpty(groupInstances)) {
1056 if (groupsMap == null) {
1057 groupsMap = new HashMap<>();
1059 for (final GroupInstance groupInst : groupInstances) {
1060 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1061 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1066 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1068 if (groupsMap != null) {
1069 log.debug("instance groups added");
1070 topologyTemplate.addGroups(groupsMap);
1072 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1073 ((Service) component).getForwardingPaths())) {
1074 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1075 ForwardingPathToscaUtil
1076 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1077 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1079 if (convertNodeTemplatesRes == null) {
1080 convertNodeTemplatesRes = Either.left(nodeTemplates);
1082 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1083 return convertNodeTemplatesRes;
1086 private Object convertToToscaObject(String value) {
1088 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1089 StringReader reader = new StringReader(value);
1090 JsonReader jsonReader = new JsonReader(reader);
1091 jsonReader.setLenient(true);
1092 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1093 if (jsonElement.isJsonObject()) {
1094 JsonObject jsonObj = jsonElement.getAsJsonObject();
1095 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1096 return mapConverterInst.handleComplexJsonValue(jsonElement);
1100 } catch (Exception e) {
1101 log.debug("convertToToscaValue failed to parse json value :", e);
1106 private Object parseToIntIfPossible(final String value) {
1107 final Integer intValue = Ints.tryParse(value);
1108 return intValue == null ? value : intValue;
1111 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1112 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1113 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1115 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1116 nodeTemplate.setInterfaces(null);
1120 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1122 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1123 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1125 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1126 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1128 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1129 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1132 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1133 return Objects.nonNull(componentInstance.getOriginType())
1134 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1137 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1138 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1139 String instanceUniqueId, Map<String, Object> props) {
1141 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1142 if (instanceInputsList != null) {
1143 instanceInputsList.forEach(input -> {
1144 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1145 : input.getDefaultValue();
1146 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1151 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1152 final Map<String, DataTypeDefinition> dataTypes,
1153 final String instanceUniqueId,
1154 final Map<String, Object> props) {
1156 if (isNotEmpty(componentInstancesProperties)) {
1157 componentInstancesProperties.get(instanceUniqueId)
1158 // Converts and adds each value to property map
1159 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1163 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1164 final String instanceUniqueId,
1165 final Map<String, Object> attribs) {
1167 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1168 componentInstancesAttributes.get(instanceUniqueId)
1169 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1173 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1174 Component componentOfInstance, Map<String, Object> props) {
1176 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1177 if (isNotEmpty(componentProperties)) {
1178 componentProperties.stream()
1179 // Filters out properties with empty default values
1180 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1181 // Converts and adds each value to property map
1182 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1186 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1188 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1189 if (isNotEmpty(componentAttributes)) {
1190 componentAttributes.stream()
1191 // Filters out Attributes with empty default values
1192 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1193 // Converts and adds each value to attribute map
1194 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1198 private ToscaNodeType createNodeType(Component component) {
1199 ToscaNodeType toscaNodeType = new ToscaNodeType();
1200 if (ModelConverter.isAtomicComponent(component)) {
1201 if (((Resource) component).getDerivedFrom() != null) {
1202 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1204 toscaNodeType.setDescription(component.getDescription());
1206 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1208 toscaNodeType.setDerived_from(derivedFrom);
1210 return toscaNodeType;
1213 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1215 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1216 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1217 List<ComponentInstance> componentInstances = container.getComponentInstances();
1218 if (CollectionUtils.isEmpty(componentInstances)) {
1221 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1222 componentInstances.stream()
1223 .filter(this::isComponentOfTypeServiceProxy)
1224 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1225 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1228 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1229 Component serviceComponent;
1230 ComponentParametersView componentParametersView = new ComponentParametersView();
1231 componentParametersView.disableAll();
1232 componentParametersView.setIgnoreInterfaces(false);
1233 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1234 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1235 if (service.isRight()) {
1236 log.debug("Failed to fetch original service component with id {} for instance {}",
1237 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1238 return Either.right(ToscaError.GENERAL_ERROR);
1240 serviceComponent = service.left().value();
1243 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1244 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1245 if (lifecycleTypeEither.isRight()) {
1246 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1247 return Either.right(ToscaError.GENERAL_ERROR);
1250 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1251 .map(InterfaceDataDefinition::getType)
1252 .collect(Collectors.toList());
1253 //Add interface types for local interfaces in the original service component for proxy
1254 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1255 allGlobalInterfaceTypes);
1256 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1257 proxyInterfaceTypes.putAll(localInterfaceTypes);
1261 return Either.left(proxyInterfaceTypes);
1264 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1265 Component container) {
1267 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1268 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1270 List<ComponentInstance> componentInstances = container.getComponentInstances();
1272 if (componentInstances == null || componentInstances.isEmpty()) {
1275 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1276 List<ComponentInstance> proxyInst = componentInstances.stream()
1277 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1278 .collect(Collectors.toList());
1279 if (proxyInst != null && !proxyInst.isEmpty()) {
1280 for (ComponentInstance inst : proxyInst) {
1281 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1285 if (serviceProxyInstanceList.isEmpty()) {
1288 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1289 .getLatestByName("serviceProxy", null);
1290 if (serviceProxyOrigin.isRight()) {
1291 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1292 serviceProxyOrigin.right().value());
1293 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1295 Component origComponent = serviceProxyOrigin.left().value();
1297 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1298 Component serviceComponent = null;
1299 ComponentParametersView componentParametersView = new ComponentParametersView();
1300 componentParametersView.disableAll();
1301 componentParametersView.setIgnoreCategories(false);
1302 componentParametersView.setIgnoreProperties(false);
1303 componentParametersView.setIgnoreInputs(false);
1304 componentParametersView.setIgnoreInterfaces(false);
1305 componentParametersView.setIgnoreRequirements(false);
1306 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1307 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1308 if (service.isRight()) {
1309 log.debug("Failed to fetch resource with id {} for instance {}",
1310 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1312 serviceComponent = service.left().value();
1315 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1316 entryProxy.getValue());
1317 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1320 return Either.left(nodeTypesMap);
1323 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1324 final Component container, final ToscaTemplate toscaNode) {
1325 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1327 if (CollectionUtils.isEmpty(componentInstances)) {
1330 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1331 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1332 .collect(Collectors.toList());
1333 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1334 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1335 final Map<String, ToscaNodeType> nodeTypes =
1336 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1337 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1343 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1344 Component proxyComponent, ComponentInstance componentInstance) {
1345 ToscaNodeType toscaNodeType = new ToscaNodeType();
1346 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1348 toscaNodeType.setDerived_from(derivedFrom);
1349 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1350 origComponent.getModel());
1351 if (dataTypesEither.isRight()) {
1352 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1354 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1355 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1356 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1358 if (MapUtils.isNotEmpty(capabilities)) {
1359 toscaNodeType.setCapabilities(capabilities);
1361 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1362 .convertProxyRequirements(componentCache, componentInstance);
1363 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1364 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1366 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1367 proxyProperties.ifPresent(toscaNodeType::setProperties);
1369 Map<String, Object> interfaceMap = new HashMap<>();
1370 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1371 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1372 if (proxyInterfaces.isPresent()) {
1373 interfaceMap = proxyInterfaces.get();
1376 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1379 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1380 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1382 return toscaNodeType;
1385 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1386 ComponentInstance componentInstance,
1387 List<RequirementCapabilityRelDef> relations,
1388 ToscaNodeTemplate nodeTypeTemplate,
1389 Component originComponent,
1390 Map<String, Component> componentCache) {
1392 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1394 if (isNotEmpty(requirementDefinitionList)) {
1396 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1397 requirementDefinitionList, originComponent, componentCache);
1398 if (!toscaRequirements.isEmpty()) {
1399 nodeTypeTemplate.setRequirements(toscaRequirements);
1401 } catch (final Exception e) {
1402 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1403 componentInstance.getName(), e);
1404 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1407 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1408 return Either.left(nodeTypeTemplate);
1411 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1412 final ComponentInstance componentInstance,
1413 final List<RequirementCapabilityRelDef> filteredRelations,
1414 final Component originComponent,
1415 final Map<String, Component> componentCache)
1416 throws ToscaExportException {
1418 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1419 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1420 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1421 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1422 toscaRequirements.add(toscaTemplateRequirementMap);
1425 return toscaRequirements;
1428 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1429 List<RequirementCapabilityRelDef> relations) {
1430 return relations.stream()
1431 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1434 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1435 final Component fromOriginComponent,
1436 final List<ComponentInstance> instancesList,
1437 final RequirementCapabilityRelDef relationshipDefinition,
1438 final Map<String, Component> componentCache)
1439 throws ToscaExportException {
1441 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1442 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1443 .getRelationships().get(0);
1444 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1446 final ComponentInstance toInstance = instancesList.stream()
1447 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1448 .findFirst().orElse(null);
1449 if (toInstance == null) {
1450 final String errorMsg = String
1451 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1452 relationshipDefinition.getToNode());
1453 log.debug(errorMsg);
1454 throw new ToscaExportException(errorMsg);
1456 final Optional<RequirementDefinition> reqOpt =
1457 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1458 if (reqOpt.isEmpty()) {
1459 final String errorMsg = String
1460 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1461 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1462 log.debug(errorMsg);
1463 throw new ToscaExportException(errorMsg);
1465 final ComponentParametersView filter = new ComponentParametersView(true);
1466 filter.setIgnoreComponentInstances(false);
1467 filter.setIgnoreCapabilities(false);
1468 filter.setIgnoreGroups(false);
1469 final Either<Component, StorageOperationStatus> getOriginRes =
1470 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1471 if (getOriginRes.isRight()) {
1472 final String errorMsg = String.format(
1473 "Failed to build substituted name for the requirement %s. "
1474 + "Failed to get an origin component with uniqueId %s",
1475 reqOpt.get().getName(), toInstance.getActualComponentUid());
1476 log.debug(errorMsg);
1477 throw new ToscaExportException(errorMsg);
1479 final Component toOriginComponent = getOriginRes.left().value();
1480 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1481 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1482 if (capOpt.isEmpty()) {
1483 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1484 if (capOpt.isEmpty()) {
1485 final String errorMsg = String
1486 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1487 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1488 log.debug(errorMsg);
1489 throw new ToscaExportException(errorMsg);
1492 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1493 capabilityRequirementRelationship, toInstance, componentCache);
1496 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1497 CapabilityDefinition capability) {
1498 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1499 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1502 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1503 Component toOriginComponent, Component fromOriginComponent,
1504 RequirementDefinition requirement) {
1505 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1506 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1507 if (!cap.isPresent()) {
1508 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1509 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1514 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1515 final Component toOriginComponent,
1516 final CapabilityDefinition capability,
1517 final RequirementDefinition requirement,
1518 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1519 final ComponentInstance toInstance,
1520 final Map<String, Component> componentCache)
1521 throws ToscaExportException {
1523 List<String> reducedPath = capability.getPath();
1524 if (capability.getOwnerId() != null) {
1525 reducedPath = capabilityRequirementConverter
1526 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1528 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1529 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1530 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1531 if (capabilityNameEither.isRight()) {
1532 final String errorMsg = String.format(
1533 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1534 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1537 throw new ToscaExportException(errorMsg);
1539 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1540 .buildSubstitutedName(componentCache, fromOriginComponent,
1541 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1542 if (requirementNameEither.isRight()) {
1543 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1544 + "with name %s on a component with uniqueId %s",
1545 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1546 log.debug(errorMsg);
1547 throw new ToscaExportException(errorMsg);
1549 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1550 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1551 toscaRequirement.setNode(toInstance.getName());
1552 toscaRequirement.setCapability(capabilityNameEither.left().value());
1553 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1554 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1556 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1560 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1561 Map<String, List<RequirementDefinition>> reqMap,
1562 RelationshipInfo reqAndRelationshipPair,
1563 String fromInstanceId) {
1564 for (List<RequirementDefinition> reqList : reqMap.values()) {
1565 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1566 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1568 if (reqOpt.isPresent()) {
1572 return Optional.empty();
1576 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1577 * 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
1578 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1580 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1581 RequirementDefinition requirement, String fromInstanceId) {
1582 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1583 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1584 reqAndRelationshipPair.getRequirement());
1587 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1591 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1592 Component originComponent) {
1593 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1594 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1595 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1598 private boolean isCvfc(Component component) {
1599 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1602 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1603 final Map<String, Component> componentCache) {
1604 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1605 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1606 if (toscaCapabilitiesRes.isRight()) {
1607 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1608 return Either.right(toscaCapabilitiesRes.right().value());
1610 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1611 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1612 return Either.left(toscaCapabilitiesRes.left().value());
1614 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1616 return Either.left(Collections.emptyMap());
1619 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1620 Map<String, DataTypeDefinition> dataTypes) {
1621 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1622 if (!toscaCapabilities.isEmpty()) {
1623 nodeType.setCapabilities(toscaCapabilities);
1625 log.debug("Finish convert Capabilities for node type");
1626 return Either.left(nodeType);
1629 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1630 if (artifacts == null) {
1633 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1634 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1635 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1636 artifact.setFile(entry.getValue().getFile());
1637 artifact.setType(entry.getValue().getType());
1638 artifact.setProperties(entry.getValue().getProperties());
1639 arts.put(entry.getKey(), artifact);
1644 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1645 if (inNodeFilter == null) {
1648 NodeFilter nodeFilter = new NodeFilter();
1649 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1650 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1651 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1652 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1653 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1654 nodeFilter.setCapabilities(capabilitiesCopy);
1656 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1657 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1658 nodeFilter.setProperties(propertiesCopy);
1660 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1661 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1665 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1666 if (substitutionFilterDataDefinition == null) {
1669 NodeFilter nodeFilter = new NodeFilter();
1670 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1671 if (!propertiesCopy.isEmpty()) {
1672 nodeFilter.setProperties(propertiesCopy);
1674 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1675 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1678 private Object cloneToscaId(Object toscaId) {
1679 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1682 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1683 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1684 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1687 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1688 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1689 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1693 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1694 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1695 final var capabilityFilter = new CapabilityFilter();
1696 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1697 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1698 capabilitiesCopy.add(capabilityFilterCopyMap);
1702 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1703 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1704 return Collections.emptyList();
1706 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1707 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1708 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1709 final String propertyName = propertyFilter.getName();
1710 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1711 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1712 if (constraints == null) {
1713 constraints = new ArrayList<>();
1715 constraints.add(buildNodeFilterValue(filterConstraint));
1720 propertyFilterDefinitionMap.entrySet().stream()
1721 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1722 .forEach(propertiesCopy::add);
1723 return propertiesCopy;
1726 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1727 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1729 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1730 return Collections.emptyList();
1732 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1733 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1734 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1735 final String propertyName = propertyFilter.getName();
1736 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1737 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1738 if (constraints == null) {
1739 constraints = new ArrayList<>();
1741 constraints.add(buildNodeFilterValue(filterConstraint));
1746 propertyFilterDefinitionMap.entrySet().stream()
1747 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1748 .forEach(propertiesCopy::add);
1749 return propertiesCopy;
1752 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1753 if (filterConstraint.getValue() instanceof ToscaFunction) {
1754 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1756 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1760 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1761 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1762 return Collections.emptyMap();
1764 Map<String, String[]> propertyMapping = new HashMap<>();
1765 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1766 Collectors.toList());
1768 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1769 propertyMappedInputList.forEach(inputDefinition -> {
1770 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1771 Optional<PropertyDefinition> property = component.getProperties().stream()
1772 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1773 if (property.isPresent()) {
1774 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1777 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1781 return propertyMapping;
1784 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1785 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1786 return Collections.emptyMap();
1788 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1789 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1792 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1793 if (Objects.isNull(proxyComponent)) {
1794 return Optional.empty();
1796 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1797 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1798 proxyProperties.putAll(proxyComponent.getProperties().stream()
1799 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1800 .toMap(PropertyDataDefinition::getName,
1801 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1803 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1806 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1807 String componentUniqueId) {
1808 if (CollectionUtils.isEmpty(componentInputs)) {
1809 return new HashMap<>();
1811 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1812 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1815 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1816 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1817 return Optional.empty();
1819 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1820 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1822 // always available in the proxy node template
1823 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1824 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1827 private static class CustomRepresenter extends Representer {
1829 CustomRepresenter() {
1831 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1832 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1833 // null representer is exceptional and it is stored as an instance
1836 this.nullRepresenter = new RepresentNull();
1839 public boolean validateGetInputValue(final Object valueObj) {
1840 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1843 if (valueObj instanceof List) {
1844 return ((List) valueObj).size() > 1;
1849 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1850 if (valueObj instanceof List) {
1851 return ((List) valueObj).size() > 1;
1857 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1858 if (propertyValue == null) {
1861 // skip not relevant for Tosca property
1862 if ("dependencies".equals(property.getName())) {
1865 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1868 if (javaBean instanceof ToscaPropertyConstraint) {
1869 return handleToscaPropertyConstraint((ToscaPropertyConstraint)javaBean, property, propertyValue, customTag);
1871 removeDefaultP(propertyValue);
1872 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1873 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1874 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1876 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1879 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1880 final Tag customTag) {
1881 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1882 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1883 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1886 private void removeDefaultP(final Object propertyValue) {
1887 if (propertyValue instanceof Map) {
1888 final Map mapPropertyValue = ((Map) propertyValue);
1889 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1890 Object defaultValue = null;
1891 while (iter.hasNext()) {
1892 final Map.Entry entry = iter.next();
1893 if ("_defaultp_".equals(entry.getKey())) {
1894 defaultValue = entry.getValue();
1896 } else if (entry.getValue() instanceof Map) {
1897 removeDefaultP(entry.getValue());
1900 if (defaultValue != null) {
1901 mapPropertyValue.putIfAbsent("default", defaultValue);
1907 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1908 // remove the bean type from the output yaml (!! ...)
1909 if (!classTags.containsKey(javaBean.getClass())) {
1910 addClassTag(javaBean.getClass(), Tag.MAP);
1912 return super.representJavaBean(properties, javaBean);
1915 private class RepresentToscaAttribute implements Represent {
1918 public Node representData(Object data) {
1919 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1920 return represent(toscaAttribute.asToscaMap());
1924 private class RepresentToscaPropertyAssignment implements Represent {
1926 public Node representData(Object data) {
1927 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1928 if (toscaOperationAssignment.getValue() instanceof String) {
1929 final String stringValue = (String) toscaOperationAssignment.getValue();
1930 if (isPropertyOrAttributeFunction(stringValue)) {
1931 return representGetAttribute(stringValue);
1933 return representScalar(Tag.STR, stringValue);
1935 return represent(null);
1938 public Node representGetAttribute(final String getAttributeFunction) {
1939 return represent(new Yaml().load(getAttributeFunction));
1942 public boolean isPropertyOrAttributeFunction(final String value) {
1944 final Yaml yaml = new Yaml();
1945 final Object yamlObj = yaml.load(value);
1946 if (!(yamlObj instanceof Map)) {
1949 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1950 if (getAttributeMap.size() != 1) {
1953 final List<String> functionList = Arrays
1954 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1955 final Optional<String> function = getAttributeMap.keySet().stream()
1956 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1957 if (function.isEmpty()) {
1960 final String functionName = function.get();
1961 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1962 if (GET_INPUT.getFunctionName().equals(functionName)) {
1963 return validateGetInputValue(getAttributeValueObj);
1965 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1967 } catch (final Exception ignored) {
1973 private class RepresentNull implements Represent {
1976 public Node representData(Object data) {
1977 // possible values are here http://yaml.org/type/null.html
1978 return representScalar(Tag.NULL, "");
1983 private static class UnsortedPropertyUtils extends PropertyUtils {
1986 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1987 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1988 return new LinkedHashSet<>(fields);
1992 private Configuration getConfiguration() {
1993 return ConfigurationManager.getConfigurationManager().getConfiguration();