2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.tosca;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.collections.MapUtils.isNotEmpty;
24 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
25 import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.google.common.primitives.Ints;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParser;
35 import com.google.gson.stream.JsonReader;
36 import fj.data.Either;
38 import java.io.StringReader;
39 import java.nio.file.Path;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedHashMap;
48 import java.util.LinkedHashSet;
49 import java.util.List;
51 import java.util.Map.Entry;
52 import java.util.Objects;
53 import java.util.Optional;
55 import java.util.function.Supplier;
56 import java.util.stream.Collectors;
58 import org.apache.commons.collections.CollectionUtils;
59 import org.apache.commons.collections.MapUtils;
60 import org.apache.commons.io.FilenameUtils;
61 import org.apache.commons.lang3.StringUtils;
62 import org.apache.commons.lang3.tuple.ImmutablePair;
63 import org.apache.commons.lang3.tuple.ImmutableTriple;
64 import org.apache.commons.lang3.tuple.Triple;
65 import org.onap.sdc.tosca.services.YamlUtil;
66 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
67 import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
68 import org.openecomp.sdc.be.config.Configuration;
69 import org.openecomp.sdc.be.config.ConfigurationManager;
70 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
71 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
72 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
82 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
83 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
84 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
85 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
86 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
87 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
88 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
89 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
90 import org.openecomp.sdc.be.exception.ToscaExportException;
91 import org.openecomp.sdc.be.model.ArtifactDefinition;
92 import org.openecomp.sdc.be.model.AttributeDefinition;
93 import org.openecomp.sdc.be.model.CapabilityDefinition;
94 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
95 import org.openecomp.sdc.be.model.Component;
96 import org.openecomp.sdc.be.model.ComponentInstance;
97 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
98 import org.openecomp.sdc.be.model.ComponentInstanceInput;
99 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
100 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
101 import org.openecomp.sdc.be.model.ComponentParametersView;
102 import org.openecomp.sdc.be.model.DataTypeDefinition;
103 import org.openecomp.sdc.be.model.GroupInstance;
104 import org.openecomp.sdc.be.model.InputDefinition;
105 import org.openecomp.sdc.be.model.InterfaceDefinition;
106 import org.openecomp.sdc.be.model.PropertyDefinition;
107 import org.openecomp.sdc.be.model.RelationshipInfo;
108 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
109 import org.openecomp.sdc.be.model.RequirementDefinition;
110 import org.openecomp.sdc.be.model.Resource;
111 import org.openecomp.sdc.be.model.Service;
112 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
113 import org.openecomp.sdc.be.model.category.CategoryDefinition;
114 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
115 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
116 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
117 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
118 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
119 import org.openecomp.sdc.be.model.tosca.ToscaType;
120 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
121 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
122 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
123 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
124 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
125 import org.openecomp.sdc.be.tosca.model.NodeFilter;
126 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
127 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
128 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
129 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
130 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
131 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
132 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
133 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
134 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
135 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
136 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
137 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
138 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
139 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
140 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
141 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
142 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
143 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
144 import org.openecomp.sdc.be.tosca.utils.InputConverter;
145 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
146 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
147 import org.openecomp.sdc.common.log.wrappers.Logger;
148 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
149 import org.springframework.beans.factory.annotation.Autowired;
150 import org.yaml.snakeyaml.DumperOptions;
151 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
152 import org.yaml.snakeyaml.Yaml;
153 import org.yaml.snakeyaml.introspector.BeanAccess;
154 import org.yaml.snakeyaml.introspector.Property;
155 import org.yaml.snakeyaml.introspector.PropertyUtils;
156 import org.yaml.snakeyaml.nodes.MappingNode;
157 import org.yaml.snakeyaml.nodes.Node;
158 import org.yaml.snakeyaml.nodes.NodeTuple;
159 import org.yaml.snakeyaml.nodes.Tag;
160 import org.yaml.snakeyaml.representer.Represent;
161 import org.yaml.snakeyaml.representer.Representer;
163 @org.springframework.stereotype.Component("tosca-export-handler")
164 public class ToscaExportHandler {
166 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
167 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
168 private static final String INVARIANT_UUID = "invariantUUID";
169 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
170 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
171 private static final String IMPORTS_FILE_KEY = "file";
172 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
173 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
174 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
175 private static final String NATIVE_ROOT = "tosca.nodes.Root";
176 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
177 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
178 private static final YamlUtil yamlUtil = new YamlUtil();
179 private final ApplicationDataTypeCache applicationDataTypeCache;
180 private final ToscaOperationFacade toscaOperationFacade;
181 private final CapabilityRequirementConverter capabilityRequirementConverter;
182 private final PolicyExportParser policyExportParser;
183 private final GroupExportParser groupExportParser;
184 private final PropertyConvertor propertyConvertor;
185 private final AttributeConverter attributeConverter;
186 private final InputConverter inputConverter;
187 private final OutputConverter outputConverter;
188 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
189 private final InterfacesOperationsConverter interfacesOperationsConverter;
190 private final ModelOperation modelOperation;
193 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
194 final ToscaOperationFacade toscaOperationFacade,
195 final CapabilityRequirementConverter capabilityRequirementConverter,
196 final PolicyExportParser policyExportParser,
197 final GroupExportParser groupExportParser,
198 final PropertyConvertor propertyConvertor,
199 final AttributeConverter attributeConverter,
200 final InputConverter inputConverter,
201 final OutputConverter outputConverter,
202 final InterfaceLifecycleOperation interfaceLifecycleOperation,
203 final InterfacesOperationsConverter interfacesOperationsConverter,
204 final ModelOperation modelOperation) {
205 this.applicationDataTypeCache = applicationDataTypeCache;
206 this.toscaOperationFacade = toscaOperationFacade;
207 this.capabilityRequirementConverter = capabilityRequirementConverter;
208 this.policyExportParser = policyExportParser;
209 this.groupExportParser = groupExportParser;
210 this.propertyConvertor = propertyConvertor;
211 this.attributeConverter = attributeConverter;
212 this.inputConverter = inputConverter;
213 this.outputConverter = outputConverter;
214 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
215 this.interfacesOperationsConverter = interfacesOperationsConverter;
216 this.modelOperation = modelOperation;
219 public static String getInterfaceFilename(String artifactName) {
220 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
223 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
224 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
227 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
228 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
231 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
232 return convertToToscaTemplate(component, false).left().map(this::createToscaRepresentation);
235 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component, Boolean isSkipImports) {
236 return convertToToscaTemplate(component, isSkipImports).left().map(this::createToscaRepresentation);
239 public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
240 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
243 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
244 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), false));
245 if (CollectionUtils.isEmpty(imports)) {
246 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
247 return Either.right(ToscaError.GENERAL_ERROR);
249 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
250 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
251 .startsWith("org.openecomp.resource.abstract.nodes.")) {
252 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
253 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
254 component.getModel());
255 if (baseType.isLeft() && baseType.left().value() != null) {
256 addDependencies(imports, dependencies, baseType.left().value(), false);
258 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
262 String toscaVersion = null;
263 if (component instanceof Resource) {
264 toscaVersion = ((Resource) component).getToscaVersion();
266 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
267 toscaTemplate.setImports(imports);
268 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
269 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
270 isAssociatedComponent);
271 if (toscaTemplateRes.isRight()) {
272 return Either.right(toscaTemplateRes.right().value());
274 toscaTemplate = toscaTemplateRes.left().value();
275 toscaTemplate.setDependencies(dependencies);
276 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
277 return Either.left(toscaRepresentation);
280 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent,
281 final boolean isSkipImports) {
282 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), isSkipImports));
283 if (CollectionUtils.isEmpty(imports)) {
284 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
285 return Either.right(ToscaError.GENERAL_ERROR);
287 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
288 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
289 .startsWith("org.openecomp.resource.abstract.nodes.")) {
290 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
291 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
292 component.getModel());
293 if (baseType.isLeft() && baseType.left().value() != null) {
294 addDependencies(imports, dependencies, baseType.left().value(), isSkipImports);
296 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
300 String toscaVersion = null;
301 if (component instanceof Resource) {
302 toscaVersion = ((Resource) component).getToscaVersion();
304 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
305 toscaTemplate.setImports(imports);
306 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
307 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
308 isAssociatedComponent);
309 if (toscaTemplateRes.isRight()) {
310 return Either.right(toscaTemplateRes.right().value());
312 toscaTemplate = toscaTemplateRes.left().value();
313 toscaTemplate.setDependencies(dependencies);
314 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
315 return Either.left(toscaRepresentation);
318 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
319 CustomRepresenter representer = new CustomRepresenter();
320 DumperOptions options = new DumperOptions();
321 options.setAllowReadOnlyProperties(false);
322 options.setPrettyFlow(true);
323 options.setDefaultFlowStyle(FlowStyle.FLOW);
324 options.setCanonical(false);
325 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
326 representer.setPropertyUtils(new UnsortedPropertyUtils());
328 Yaml yaml = new Yaml(representer, options);
329 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
330 String sb = getConfiguration().getHeatEnvArtifactHeader()
332 + getConfiguration().getHeatEnvArtifactFooter();
333 return ToscaRepresentation.make(sb.getBytes(), toscaTemplate);
336 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
337 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
338 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, false);
339 if (fillImports.isRight()) {
340 return Either.right(fillImports.right().value());
342 return Either.left(fillImports.left().value().left);
345 public Either<ToscaTemplate, ToscaError> getDependencies(Component component, boolean isSkipImports) {
346 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
347 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, isSkipImports);
348 if (fillImports.isRight()) {
349 return Either.right(fillImports.right().value());
351 return Either.left(fillImports.left().value().left);
354 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component, final boolean isSkipImports) {
355 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
356 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
357 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
358 return Either.right(ToscaError.GENERAL_ERROR);
360 log.trace("start tosca export for {}", component.getUniqueId());
361 String toscaVersion = null;
362 if (component instanceof Resource) {
363 toscaVersion = ((Resource) component).getToscaVersion();
365 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
366 toscaTemplate.setMetadata(convertMetadata(component));
367 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
368 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
369 if (ModelConverter.isAtomicComponent(component)) {
370 log.trace("convert component as node type");
371 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
373 log.trace("convert component as topology template");
374 return convertToscaTemplate(component, toscaTemplate, isSkipImports);
378 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
379 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
380 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
383 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
384 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
385 if (dataTypesEither.isRight()) {
386 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
387 return Either.right(ToscaError.GENERAL_ERROR);
389 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
390 if (!dataTypeDefinition.isEmpty()) {
391 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
392 ToscaDataType toscaDataType = new ToscaDataType();
393 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
394 toscaDataType.setDescription(dataTypeDefinition.getDescription());
395 toscaDataType.setVersion(dataTypeDefinition.getVersion());
396 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
397 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
398 .collect(Collectors.toMap(
399 PropertyDataDefinition::getName,
400 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
401 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition,
402 toscaPropertyTobeValidated,
406 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
407 toscaTemplate.setData_types(toscaDataTypeMap);
409 return Either.left(toscaTemplate);
412 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId, final boolean isSkipImports) {
413 if (StringUtils.isEmpty(modelId)) {
414 return getDefaultToscaImportConfig();
417 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
418 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
419 final Set<Path> addedPathList = new HashSet<>();
420 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
421 var importPath = Path.of(toscaImportByModel.getFullPath());
422 if (!(isSkipImports && importPath.toString().equals(ADDITIONAL_TYPE_DEFINITIONS))) {
423 if (addedPathList.contains(importPath)) {
425 ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
427 final String fileName = FilenameUtils.getBaseName(importPath.toString());
428 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
429 addedPathList.add(importPath);
435 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode, boolean isSkipImports) {
436 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode, isSkipImports);
437 if (importsRes.isRight()) {
438 return Either.right(importsRes.right().value());
440 toscaNode = importsRes.left().value().left;
441 Map<String, Component> componentCache = importsRes.left().value().right;
442 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
443 if (nodeTypesMapEither.isRight()) {
444 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
445 return Either.right(nodeTypesMapEither.right().value());
447 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
448 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
449 toscaNode.setNode_types(nodeTypesMap);
451 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
452 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
453 if (proxyInterfaceTypesEither.isRight()) {
454 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
455 return Either.right(proxyInterfaceTypesEither.right().value());
457 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
458 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
459 toscaNode.setInterface_types(proxyInterfaceTypes);
461 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
462 if (dataTypesEither.isRight()) {
463 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
464 return Either.right(ToscaError.GENERAL_ERROR);
466 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
467 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
468 List<InputDefinition> inputDef = component.getInputs();
469 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
470 if (!inputs.isEmpty()) {
471 topologyTemplate.setInputs(inputs);
473 final Map<String, ToscaProperty> outputs;
475 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
476 } catch (final ToscaConversionException e) {
477 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
478 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
479 return Either.right(ToscaError.GENERAL_ERROR);
481 if (!outputs.isEmpty()) {
482 topologyTemplate.setOutputs(outputs);
484 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
485 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
486 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
487 if (nodeTemplates.isRight()) {
488 return Either.right(nodeTemplates.right().value());
490 log.debug("node templates converted");
491 topologyTemplate.setNode_templates(nodeTemplates.left().value());
493 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
494 .createFrom(topologyTemplate.getNode_templates());
495 if (!relationshipTemplatesMap.isEmpty()) {
496 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
498 addGroupsToTopologyTemplate(component, topologyTemplate);
500 addPoliciesToTopologyTemplate(component, topologyTemplate);
501 } catch (SdcResourceNotFoundException e) {
502 log.debug("Fail to add policies to topology template:", e);
503 return Either.right(ToscaError.GENERAL_ERROR);
506 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
507 } catch (final ToscaExportException e) {
508 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
509 return Either.right(e.getToscaError());
511 if (!topologyTemplate.isEmpty()) {
512 toscaNode.setTopology_template(topologyTemplate);
514 return Either.left(toscaNode);
517 private Either<String, ToscaError> createComponentToscaName(final Component component) {
518 switch (component.getComponentType()) {
520 final ResourceMetadataDataDefinition resourceMetadata =
521 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
522 return Either.left(resourceMetadata.getToscaResourceName());
524 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
526 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
527 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
531 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
532 final Map<String, Component> componentCache) throws ToscaExportException {
533 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
534 return Optional.empty();
537 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
538 if (toscaResourceNameEither.isRight()) {
539 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
541 final String toscaResourceName = toscaResourceNameEither.left().value();
543 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
544 if (doNotExtendBaseType(component)) {
545 substitutionMapping.setNode_type(component.getDerivedFromGenericType());
547 substitutionMapping.setNode_type(toscaResourceName);
549 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
551 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
552 if (capabilitiesEither.isRight()) {
553 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
555 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
556 if (!capabilityMap.isEmpty()) {
557 substitutionMapping.setCapabilities(capabilityMap);
559 final Either<Map<String, String[]>, ToscaError> requirements =
560 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
561 if (requirements.isRight()) {
562 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
564 final Map<String, String[]> requirementMap = requirements.left().value();
565 if (MapUtils.isNotEmpty(requirementMap)) {
566 substitutionMapping.setRequirements(requirementMap);
569 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
570 if (MapUtils.isNotEmpty(propertyMappingMap)) {
571 substitutionMapping.setProperties(propertyMappingMap);
574 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
575 if (MapUtils.isNotEmpty(attributesMappingMap)) {
576 substitutionMapping.setAttributes(attributesMappingMap);
579 return Optional.of(substitutionMapping);
582 private boolean doNotExtendBaseType(final Component component) {
583 final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig = ConfigurationManager.getConfigurationManager().getConfiguration()
584 .getServiceBaseNodeTypes();
585 List<CategoryDefinition> categories = component.getCategories();
586 if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
587 && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
588 return serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
593 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
594 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
595 return Optional.empty();
598 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
601 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
602 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
603 if (groups != null) {
604 topologyTemplate.addGroups(groups);
608 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
609 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
610 if (policies != null) {
611 topologyTemplate.addPolicies(policies);
615 private Map<String, Object> convertMetadata(Component component) {
616 return convertMetadata(component, false, null);
619 private Map<String, Object> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
620 Map<String, Object> toscaMetadata = new LinkedHashMap<>();
621 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
622 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
624 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
625 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
626 List<CategoryDefinition> categories = component.getCategories();
627 CategoryDefinition categoryDefinition = categories.get(0);
628 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
629 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
631 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
632 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
633 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
634 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
635 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
636 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
637 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
638 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
639 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
640 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
641 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
642 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
643 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
645 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
648 switch (component.getComponentType()) {
650 Resource resource = (Resource) component;
651 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
652 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
653 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
655 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
657 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
658 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
659 if (resource.getTenant() != null) {
660 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
662 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
663 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
664 toscaMetadata.put(resource.isTopologyTemplate() ? JsonPresentationFields.TEMPLATE_VERSION.getPresentation() : JsonPresentationFields.VERSION.getPresentation(), resource.getVersion());
667 Service service = (Service) component;
668 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
669 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
670 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
671 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
672 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
673 toscaMetadata.put(JsonPresentationFields.TEMPLATE_VERSION.getPresentation(), service.getVersion());
674 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
675 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
677 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
678 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
682 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
684 for (final String key : component.getCategorySpecificMetadata().keySet()) {
685 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
686 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
689 return toscaMetadata;
692 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
693 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
694 return INVARIANT_UUID;
696 return jsonPresentationField.getPresentation();
699 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate, boolean isSkipImports) {
700 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
701 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
702 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
703 return Either.right(ToscaError.GENERAL_ERROR);
705 Map<String, Component> componentCache = new HashMap<>();
706 if (!ModelConverter.isAtomicComponent(component)) {
707 final List<Map<String, Map<String, String>>> additionalImports =
708 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
709 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
710 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
711 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
712 if (!substituteTypeImportEntry.isEmpty()) {
713 additionalImports.add(substituteTypeImportEntry);
715 List<ComponentInstance> componentInstances = component.getComponentInstances();
716 if (componentInstances != null && !componentInstances.isEmpty()) {
717 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci, isSkipImports));
719 toscaTemplate.setDependencies(dependencies);
720 toscaTemplate.setImports(additionalImports);
722 log.debug("currently imports supported for VF and service only");
724 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
727 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
728 final Map<String, ArtifactDefinition> toscaArtifacts) {
729 if (doNotExtendBaseType(component)) {
730 return Collections.emptyMap();
732 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
733 return Collections.emptyMap();
735 if (MapUtils.isEmpty(toscaArtifacts)) {
736 return Collections.emptyMap();
738 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
739 if (artifactDefinition == null) {
740 return Collections.emptyMap();
742 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
743 return Map.of(importEntryName,
744 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
748 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
749 return getConfiguration().getDefaultImports();
752 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
753 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance,
754 final boolean isSkipImports) {
755 log.debug("createDependency componentCache {}", componentCache);
756 Component componentRI = componentCache.get(componentInstance.getComponentUid());
757 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
758 // all resource must be only once!
759 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
760 if ((resource.isRight()) && (log.isDebugEnabled())) {
761 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
762 componentInstance.getUniqueId());
765 final Component fetchedComponent = resource.left().value();
766 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
767 addDependencies(imports, dependencies, componentRI, isSkipImports);
772 * Sets a componentCache from the given component/resource.
774 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
775 final Component fetchedComponent) {
776 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
777 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
778 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
779 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
780 .getToscaFullElement(componentInstance.getSourceModelUid());
781 if (sourceService.isRight() && (log.isDebugEnabled())) {
782 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
783 componentInstance.getUniqueId());
785 final Component fetchedSource = sourceService.left().value();
786 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
787 return fetchedSource;
789 return fetchedComponent;
793 * Retrieves all derived_from nodes and stores it in a predictable order.
795 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
796 final Component fetchedComponent, final boolean isSkipImports) {
797 final Set<Component> componentsList = new LinkedHashSet<>();
798 if (fetchedComponent instanceof Resource) {
799 log.debug("fetchedComponent is a resource {}", fetchedComponent);
800 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
801 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
802 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
803 log.debug("Started entry.getValue() : {}", entry.getValue());
804 if (!NATIVE_ROOT.equals(entry.getValue())) {
805 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
806 if (resourcefetched != null && resourcefetched.isLeft()) {
807 componentsList.add(resourcefetched.left().value());
811 setImports(imports, dependencies, componentsList, isSkipImports);
813 setImports(imports, dependencies, fetchedComponent, isSkipImports);
819 * Returns all derived_from nodes found.
821 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
822 final Resource parentResource = (Resource) fetchedComponent;
823 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
824 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
825 componentsList.add(fetchedComponent);
826 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
827 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
828 .getToscaElement(componentInstance.getComponentUid());
829 if (resourcefetched != null && resourcefetched.isLeft()) {
830 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
831 if (MapUtils.isNotEmpty(derivedWithId)) {
832 derivedFromMapOfIdToName.putAll(derivedWithId);
837 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
839 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
840 return Optional.ofNullable(derivedFromMapOfIdToName);
844 * Creates a resource map and adds it to the import list.
846 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
847 final Set<Component> componentsList, boolean isSkipImports) {
848 componentsList.forEach(component -> setImports(imports, dependencies, component, isSkipImports));
851 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
852 final Component component, boolean isSkipImports) {
853 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
854 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
855 if (artifactDefinition != null) {
856 final Map<String, String> files = new HashMap<>();
857 final String artifactName = artifactDefinition.getArtifactName();
858 files.put(IMPORTS_FILE_KEY, artifactName);
859 final StringBuilder keyNameBuilder = new StringBuilder();
860 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
861 keyNameBuilder.append("-");
862 keyNameBuilder.append(component.getName());
863 if (!isSkipImports) {
864 addImports(imports, keyNameBuilder, files);
866 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
867 if (!ModelConverter.isAtomicComponent(component) && !isSkipImports) {
868 final Map<String, String> interfaceFiles = new HashMap<>();
869 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
870 keyNameBuilder.append("-interface");
871 addImports(imports, keyNameBuilder, interfaceFiles);
877 * Adds the found resource to the import definition list.
879 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
880 final Map<String, String> files) {
881 final String mapKey = keyNameBuilder.toString();
882 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
883 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
884 importsListMember.put(keyNameBuilder.toString(), files);
885 imports.add(importsListMember);
889 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
890 Map<String, ToscaNodeType> nodeTypes) {
891 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
894 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
895 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
896 boolean isAssociatedComponent) {
897 log.debug("start convert node type for {}", component.getUniqueId());
898 ToscaNodeType toscaNodeType = createNodeType(component);
899 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
900 .getAllInterfaceLifecycleTypes(component.getModel());
901 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
902 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
903 return Either.right(ToscaError.GENERAL_ERROR);
905 if (lifecycleTypeEither.isLeft()) {
906 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
907 .collect(Collectors.toList());
908 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
910 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
911 if (dataTypesEither.isRight()) {
912 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
913 return Either.right(ToscaError.GENERAL_ERROR);
915 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
916 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
917 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
918 if (!toscaAttributeMap.isEmpty()) {
919 toscaNodeType.setAttributes(toscaAttributeMap);
921 Map<String, ToscaProperty> convertedProperties = new HashMap();
922 if (CollectionUtils.isNotEmpty(component.getProperties())) {
923 List<PropertyDefinition> properties = component.getProperties();
924 convertedProperties = properties.stream()
925 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
926 .toMap(PropertyDataDefinition::getName,
927 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
929 if (MapUtils.isNotEmpty(convertedProperties)) {
930 toscaNodeType.setProperties(convertedProperties);
932 /* convert private data_types */
933 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
934 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
935 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
936 for (DataTypeDefinition dataType : privateDataTypes) {
937 log.debug("Emitting private data type: component.name={} dataType.name={}",
938 component.getNormalizedName(), dataType.getName());
939 ToscaDataType toscaDataType = new ToscaDataType();
940 toscaDataType.setDerived_from(dataType.getDerivedFromName());
941 toscaDataType.setDescription(dataType.getDescription());
942 toscaDataType.setVersion(dataType.getVersion());
943 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
944 toscaDataType.setProperties(dataType.getProperties().stream()
945 .collect(Collectors.toMap(
946 PropertyDataDefinition::getName,
947 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
948 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
952 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
954 toscaNode.setData_types(toscaDataTypeMap);
957 // Extracted to method for code reuse
958 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
961 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
962 final ToscaProperty toscaProperty) {
963 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
964 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
965 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
968 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
969 final Map<String, DataTypeDefinition> dataTypes) {
970 if (CollectionUtils.isEmpty(attributeList)) {
971 return Collections.emptyMap();
973 final AttributeConverter converter = new AttributeConverter(dataTypes);
974 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
975 for (final AttributeDefinition attributeDefinition : attributeList) {
976 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
978 return toscaAttributeMap;
981 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
982 Component component, ToscaTemplate toscaNode,
983 Map<String, ToscaNodeType> nodeTypes,
984 ToscaNodeType toscaNodeType,
985 Map<String, DataTypeDefinition> dataTypes) {
986 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
988 if (capabilities.isRight()) {
989 return Either.right(capabilities.right().value());
991 toscaNodeType = capabilities.left().value();
992 log.debug("Capabilities converted for {}", component.getUniqueId());
994 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
995 .convertRequirements(componentsCache, component, toscaNodeType);
996 if (requirements.isRight()) {
997 return Either.right(requirements.right().value());
999 toscaNodeType = requirements.left().value();
1000 log.debug("Requirements converted for {}", component.getUniqueId());
1002 String toscaResourceName;
1003 switch (component.getComponentType()) {
1005 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
1006 .getMetadataDataDefinition()).getToscaResourceName();
1009 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
1010 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
1013 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
1014 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1017 nodeTypes.put(toscaResourceName, toscaNodeType);
1018 toscaNode.setNode_types(nodeTypes);
1019 log.debug("finish convert node type for {}", component.getUniqueId());
1020 return Either.left(toscaNode);
1023 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
1024 final Map<String, Component> componentCache,
1025 final Map<String, DataTypeDefinition> dataTypes,
1026 final ToscaTopolgyTemplate topologyTemplate) {
1028 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
1029 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
1030 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
1031 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
1032 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
1034 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
1035 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1036 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
1038 Map<String, ToscaGroupTemplate> groupsMap = null;
1039 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
1040 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
1041 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
1042 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
1044 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
1045 List<Object> occur = new ArrayList<>();
1046 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
1047 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
1048 nodeTemplate.setOccurrences(occur);
1050 if (componentInstance.getInstanceCount() != null) {
1051 ObjectMapper objectMapper = new ObjectMapper();
1052 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
1054 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
1055 nodeTemplate.setInstance_count(map);
1058 nodeTemplate.setType(componentInstance.getToscaComponentName());
1059 nodeTemplate.setDirectives(componentInstance.getDirectives());
1060 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1061 if (nodeFilter != null && nodeFilter.hasData()) {
1062 nodeTemplate.setNode_filter(nodeFilter);
1064 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1065 .getOriginComponent(componentCache, componentInstance);
1066 if (originComponentRes.isRight()) {
1067 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1070 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1071 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1072 if (requirements.isRight()) {
1073 convertNodeTemplatesRes = Either.right(requirements.right().value());
1076 final String instanceUniqueId = componentInstance.getUniqueId();
1077 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1079 nodeTemplate = requirements.left().value();
1081 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1083 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1084 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1085 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1087 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1090 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1091 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1092 if (capabilities.isRight()) {
1093 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1096 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1098 nodeTemplate = capabilities.left().value();
1099 final Map<String, Object> props = new HashMap<>();
1100 final Map<String, Object> attribs = new HashMap<>();
1102 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1103 // Adds the properties of parent component to map
1104 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1105 addAttributesOfParentComponent(originalComponent, attribs);
1108 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1109 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1111 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1112 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1115 if (componentInstancesInputs != null
1116 && componentInstancesInputs.containsKey(instanceUniqueId)
1117 && !isComponentOfTypeServiceProxy(componentInstance)) {
1118 //For service proxy the inputs are already handled under instance properties above
1119 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1122 //M3[00001] - NODE TEMPLATE INTERFACES - START
1123 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1124 //M3[00001] - NODE TEMPLATE INTERFACES - END
1125 if (MapUtils.isNotEmpty(props)) {
1126 nodeTemplate.setProperties(props);
1128 if (MapUtils.isNotEmpty(attribs)) {
1129 nodeTemplate.setAttributes(attribs);
1132 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1133 if (CollectionUtils.isNotEmpty(groupInstances)) {
1134 if (groupsMap == null) {
1135 groupsMap = new HashMap<>();
1137 for (final GroupInstance groupInst : groupInstances) {
1138 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1139 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1144 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1146 if (groupsMap != null) {
1147 log.debug("instance groups added");
1148 topologyTemplate.addGroups(groupsMap);
1150 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1151 ((Service) component).getForwardingPaths())) {
1152 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1153 ForwardingPathToscaUtil
1154 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1155 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1157 if (convertNodeTemplatesRes == null) {
1158 convertNodeTemplatesRes = Either.left(nodeTemplates);
1160 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1161 return convertNodeTemplatesRes;
1164 private Object convertToToscaObject(String value) {
1166 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1167 StringReader reader = new StringReader(value);
1168 JsonReader jsonReader = new JsonReader(reader);
1169 jsonReader.setLenient(true);
1170 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1171 if (jsonElement.isJsonObject()) {
1172 JsonObject jsonObj = jsonElement.getAsJsonObject();
1173 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1174 return mapConverterInst.handleComplexJsonValue(jsonElement);
1178 } catch (Exception e) {
1179 log.debug("convertToToscaValue failed to parse json value :", e);
1184 private Object parseToIntIfPossible(final String value) {
1185 final Integer intValue = Ints.tryParse(value);
1186 return intValue == null ? value : intValue;
1189 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1190 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1191 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1193 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1194 nodeTemplate.setInterfaces(null);
1198 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1200 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1201 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1203 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1204 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1206 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1207 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1210 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1211 return Objects.nonNull(componentInstance.getOriginType())
1212 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1215 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1216 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1217 String instanceUniqueId, Map<String, Object> props) {
1219 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1220 if (instanceInputsList != null) {
1221 instanceInputsList.forEach(input -> {
1222 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1223 : input.getDefaultValue();
1224 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1229 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1230 final Map<String, DataTypeDefinition> dataTypes,
1231 final String instanceUniqueId,
1232 final Map<String, Object> props) {
1234 if (isNotEmpty(componentInstancesProperties)) {
1235 componentInstancesProperties.get(instanceUniqueId)
1236 // Converts and adds each value to property map
1237 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1241 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1242 final String instanceUniqueId,
1243 final Map<String, Object> attribs) {
1245 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1246 componentInstancesAttributes.get(instanceUniqueId)
1247 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1251 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1252 Component componentOfInstance, Map<String, Object> props) {
1254 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1255 if (isNotEmpty(componentProperties)) {
1256 componentProperties.stream()
1257 // Filters out properties with empty default values
1258 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1259 // Converts and adds each value to property map
1260 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1264 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1266 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1267 if (isNotEmpty(componentAttributes)) {
1268 componentAttributes.stream()
1269 // Filters out Attributes with empty default values
1270 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1271 // Converts and adds each value to attribute map
1272 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1276 private ToscaNodeType createNodeType(Component component) {
1277 ToscaNodeType toscaNodeType = new ToscaNodeType();
1278 if (ModelConverter.isAtomicComponent(component)) {
1279 if (((Resource) component).getDerivedFrom() != null) {
1280 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1282 toscaNodeType.setDescription(component.getDescription());
1284 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1286 toscaNodeType.setDerived_from(derivedFrom);
1288 return toscaNodeType;
1291 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1293 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1294 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1295 List<ComponentInstance> componentInstances = container.getComponentInstances();
1296 if (CollectionUtils.isEmpty(componentInstances)) {
1299 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1300 componentInstances.stream()
1301 .filter(this::isComponentOfTypeServiceProxy)
1302 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1303 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1306 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1307 Component serviceComponent;
1308 ComponentParametersView componentParametersView = new ComponentParametersView();
1309 componentParametersView.disableAll();
1310 componentParametersView.setIgnoreInterfaces(false);
1311 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1312 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1313 if (service.isRight()) {
1314 log.debug("Failed to fetch original service component with id {} for instance {}",
1315 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1316 return Either.right(ToscaError.GENERAL_ERROR);
1318 serviceComponent = service.left().value();
1321 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1322 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1323 if (lifecycleTypeEither.isRight()) {
1324 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1325 return Either.right(ToscaError.GENERAL_ERROR);
1328 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1329 .map(InterfaceDataDefinition::getType)
1330 .collect(Collectors.toList());
1331 //Add interface types for local interfaces in the original service component for proxy
1332 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1333 allGlobalInterfaceTypes);
1334 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1335 proxyInterfaceTypes.putAll(localInterfaceTypes);
1339 return Either.left(proxyInterfaceTypes);
1342 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1343 Component container) {
1345 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1346 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1348 List<ComponentInstance> componentInstances = container.getComponentInstances();
1350 if (componentInstances == null || componentInstances.isEmpty()) {
1353 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1354 List<ComponentInstance> proxyInst = componentInstances.stream()
1355 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1356 .collect(Collectors.toList());
1357 if (proxyInst != null && !proxyInst.isEmpty()) {
1358 for (ComponentInstance inst : proxyInst) {
1359 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1363 if (serviceProxyInstanceList.isEmpty()) {
1366 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1367 .getLatestByName("serviceProxy", null);
1368 if (serviceProxyOrigin.isRight()) {
1369 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1370 serviceProxyOrigin.right().value());
1371 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1373 Component origComponent = serviceProxyOrigin.left().value();
1375 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1376 Component serviceComponent = null;
1377 ComponentParametersView componentParametersView = new ComponentParametersView();
1378 componentParametersView.disableAll();
1379 componentParametersView.setIgnoreCategories(false);
1380 componentParametersView.setIgnoreProperties(false);
1381 componentParametersView.setIgnoreInputs(false);
1382 componentParametersView.setIgnoreInterfaces(false);
1383 componentParametersView.setIgnoreRequirements(false);
1384 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1385 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1386 if (service.isRight()) {
1387 log.debug("Failed to fetch resource with id {} for instance {}",
1388 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1390 serviceComponent = service.left().value();
1393 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1394 entryProxy.getValue());
1395 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1398 return Either.left(nodeTypesMap);
1401 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1402 final Component container, final ToscaTemplate toscaNode) {
1403 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1405 if (CollectionUtils.isEmpty(componentInstances)) {
1408 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1409 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1410 .collect(Collectors.toList());
1411 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1412 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1413 final Map<String, ToscaNodeType> nodeTypes =
1414 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1415 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1421 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1422 Component proxyComponent, ComponentInstance componentInstance) {
1423 ToscaNodeType toscaNodeType = new ToscaNodeType();
1424 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1426 toscaNodeType.setDerived_from(derivedFrom);
1427 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1428 origComponent.getModel());
1429 if (dataTypesEither.isRight()) {
1430 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1432 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1433 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1434 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1436 if (MapUtils.isNotEmpty(capabilities)) {
1437 toscaNodeType.setCapabilities(capabilities);
1439 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1440 .convertProxyRequirements(componentCache, componentInstance);
1441 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1442 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1444 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1445 proxyProperties.ifPresent(toscaNodeType::setProperties);
1447 Map<String, Object> interfaceMap = new HashMap<>();
1448 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1449 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1450 if (proxyInterfaces.isPresent()) {
1451 interfaceMap = proxyInterfaces.get();
1454 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1457 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1458 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1460 return toscaNodeType;
1463 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1464 ComponentInstance componentInstance,
1465 List<RequirementCapabilityRelDef> relations,
1466 ToscaNodeTemplate nodeTypeTemplate,
1467 Component originComponent,
1468 Map<String, Component> componentCache) {
1470 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1472 if (isNotEmpty(requirementDefinitionList)) {
1474 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1475 requirementDefinitionList, originComponent, componentCache);
1476 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1477 nodeTypeTemplate.setRequirements(toscaRequirements);
1479 } catch (final Exception e) {
1480 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1481 componentInstance.getName(), e);
1482 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1485 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1486 return Either.left(nodeTypeTemplate);
1489 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1490 final ComponentInstance componentInstance,
1491 final List<RequirementCapabilityRelDef> filteredRelations,
1492 final Component originComponent,
1493 final Map<String, Component> componentCache)
1494 throws ToscaExportException {
1496 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1497 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1498 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1499 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1500 if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1501 toscaRequirements.add(toscaTemplateRequirementMap);
1505 return toscaRequirements;
1508 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1509 List<RequirementCapabilityRelDef> relations) {
1510 return relations.stream()
1511 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1514 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1515 final Component fromOriginComponent,
1516 final List<ComponentInstance> instancesList,
1517 final RequirementCapabilityRelDef relationshipDefinition,
1518 final Map<String, Component> componentCache)
1519 throws ToscaExportException {
1521 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1522 if (MapUtils.isEmpty(reqMap)) {
1523 return new HashMap<>();
1525 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1526 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1528 final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1529 .findFirst().orElse(null);
1530 if (toInstance == null) {
1531 final String errorMsg = String
1532 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1533 relationshipDefinition.getToNode());
1534 log.debug(errorMsg);
1535 throw new ToscaExportException(errorMsg);
1537 final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1538 if (reqOpt.isEmpty()) {
1539 final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1540 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1541 log.debug(errorMsg);
1542 throw new ToscaExportException(errorMsg);
1544 final ComponentParametersView filter = new ComponentParametersView(true);
1545 filter.setIgnoreComponentInstances(false);
1546 filter.setIgnoreCapabilities(false);
1547 filter.setIgnoreGroups(false);
1548 final Either<Component, StorageOperationStatus> getOriginRes =
1549 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1550 if (getOriginRes.isRight()) {
1551 final String errorMsg = String.format(
1552 "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1553 reqOpt.get().getName(), toInstance.getActualComponentUid());
1554 log.debug(errorMsg);
1555 throw new ToscaExportException(errorMsg);
1557 final Component toOriginComponent = getOriginRes.left().value();
1558 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1559 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1560 if (capOpt.isEmpty()) {
1561 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1562 if (capOpt.isEmpty()) {
1563 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1564 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1565 log.debug(errorMsg);
1566 throw new ToscaExportException(errorMsg);
1569 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1570 capabilityRequirementRelationship, toInstance, componentCache);
1573 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1574 CapabilityDefinition capability) {
1575 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1576 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1579 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1580 Component toOriginComponent, Component fromOriginComponent,
1581 RequirementDefinition requirement) {
1582 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1583 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1584 if (cap.isEmpty()) {
1585 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1586 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1591 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1592 final Component toOriginComponent,
1593 final CapabilityDefinition capability,
1594 final RequirementDefinition requirement,
1595 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1596 final ComponentInstance toInstance,
1597 final Map<String, Component> componentCache)
1598 throws ToscaExportException {
1600 List<String> reducedPath = capability.getPath();
1601 if (capability.getOwnerId() != null) {
1602 reducedPath = capabilityRequirementConverter
1603 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1605 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1606 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1607 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1608 if (capabilityNameEither.isRight()) {
1609 final String errorMsg = String.format(
1610 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1611 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1614 throw new ToscaExportException(errorMsg);
1616 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1617 .buildSubstitutedName(componentCache, fromOriginComponent,
1618 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1619 if (requirementNameEither.isRight()) {
1620 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1621 + "with name %s on a component with uniqueId %s",
1622 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1623 log.debug(errorMsg);
1624 throw new ToscaExportException(errorMsg);
1626 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1627 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1628 toscaRequirement.setNode(toInstance.getName());
1629 toscaRequirement.setCapability(capabilityNameEither.left().value());
1630 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1631 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1633 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1637 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1638 Map<String, List<RequirementDefinition>> reqMap,
1639 RelationshipInfo reqAndRelationshipPair,
1640 String fromInstanceId) {
1641 for (final List<RequirementDefinition> reqList : reqMap.values()) {
1642 final Optional<RequirementDefinition> reqOpt = reqList.stream()
1643 .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1644 if (reqOpt.isPresent()) {
1648 return Optional.empty();
1652 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1653 * 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
1654 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1656 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1657 RequirementDefinition requirement, String fromInstanceId) {
1658 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1661 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1662 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1663 reqAndRelationshipPair.getRequirement());
1666 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1670 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1671 Component originComponent) {
1672 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1673 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1674 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1677 private boolean isCvfc(Component component) {
1678 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1681 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1682 final Map<String, Component> componentCache) {
1683 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1684 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1685 if (toscaCapabilitiesRes.isRight()) {
1686 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1687 return Either.right(toscaCapabilitiesRes.right().value());
1689 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1690 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1691 return Either.left(toscaCapabilitiesRes.left().value());
1693 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1695 return Either.left(Collections.emptyMap());
1698 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1699 Map<String, DataTypeDefinition> dataTypes) {
1700 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1701 if (!toscaCapabilities.isEmpty()) {
1702 nodeType.setCapabilities(toscaCapabilities);
1704 log.debug("Finish convert Capabilities for node type");
1705 return Either.left(nodeType);
1708 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1709 if (artifacts == null) {
1712 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1713 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1714 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1715 artifact.setFile(entry.getValue().getFile());
1716 artifact.setType(entry.getValue().getType());
1717 artifact.setProperties(entry.getValue().getProperties());
1718 arts.put(entry.getKey(), artifact);
1723 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1724 if (inNodeFilter == null) {
1727 NodeFilter nodeFilter = new NodeFilter();
1728 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1729 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1730 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1731 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1732 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1733 nodeFilter.setCapabilities(capabilitiesCopy);
1735 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1736 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1737 nodeFilter.setProperties(propertiesCopy);
1739 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1740 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1743 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1744 if (substitutionFilterDataDefinition == null) {
1747 NodeFilter nodeFilter = new NodeFilter();
1748 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1749 if (!propertiesCopy.isEmpty()) {
1750 nodeFilter.setProperties(propertiesCopy);
1752 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1753 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1756 private Object cloneToscaId(Object toscaId) {
1757 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1760 private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
1761 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1762 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1765 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1766 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1767 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1771 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1772 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1773 final var capabilityFilter = new CapabilityFilter();
1774 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1775 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1776 capabilitiesCopy.add(capabilityFilterCopyMap);
1780 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1781 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1782 return Collections.emptyList();
1784 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1785 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1786 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1787 final String propertyName = propertyFilter.getName();
1788 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1789 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1790 if (constraints == null) {
1791 constraints = new ArrayList<>();
1793 constraints.add(buildNodeFilterValue(filterConstraint));
1798 propertyFilterDefinitionMap.entrySet().stream()
1799 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1800 .forEach(propertiesCopy::add);
1801 return propertiesCopy;
1804 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1805 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1807 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1808 return Collections.emptyList();
1810 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1811 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1812 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1813 final String propertyName = propertyFilter.getName();
1814 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1815 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1816 if (constraints == null) {
1817 constraints = new ArrayList<>();
1819 constraints.add(buildNodeFilterValue(filterConstraint));
1824 propertyFilterDefinitionMap.entrySet().stream()
1825 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1826 .forEach(propertiesCopy::add);
1827 return propertiesCopy;
1830 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1831 if (filterConstraint.getValue() instanceof ToscaFunction) {
1832 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1834 if (filterConstraint.getValue() instanceof List) {
1835 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1836 List<Object> toscaFunctionList = new ArrayList<>();
1837 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1838 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1839 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1842 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1843 ToscaType toscaType = ToscaType.getToscaType(
1844 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1845 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1846 } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1847 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1848 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1849 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1851 if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1852 filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1853 String.valueOf(filterConstraint.getValue())));
1855 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1858 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1859 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1860 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1863 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1866 private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1867 return ToscaType.BOOLEAN.getType().equals(propertyType);
1870 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1871 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1872 return Collections.emptyMap();
1874 Map<String, String[]> propertyMapping = new HashMap<>();
1875 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1876 Collectors.toList());
1878 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1879 propertyMappedInputList.forEach(inputDefinition -> {
1880 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1881 Optional<PropertyDefinition> property = component.getProperties().stream()
1882 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1883 if (property.isPresent()) {
1884 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1887 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1891 return propertyMapping;
1894 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1895 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1896 return Collections.emptyMap();
1898 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1899 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1902 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1903 if (Objects.isNull(proxyComponent)) {
1904 return Optional.empty();
1906 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1907 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1908 proxyProperties.putAll(proxyComponent.getProperties().stream()
1909 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1910 .toMap(PropertyDataDefinition::getName,
1911 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1913 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1916 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1917 String componentUniqueId) {
1918 if (CollectionUtils.isEmpty(componentInputs)) {
1919 return new HashMap<>();
1921 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1922 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1925 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1926 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1927 return Optional.empty();
1929 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1930 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1932 // always available in the proxy node template
1933 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1934 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1937 private Configuration getConfiguration() {
1938 return ConfigurationManager.getConfigurationManager().getConfiguration();
1941 private static class CustomRepresenter extends Representer {
1943 CustomRepresenter() {
1944 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1945 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1946 // null representer is exceptional and it is stored as an instance
1949 this.nullRepresenter = new RepresentNull();
1952 public boolean validateGetInputValue(final Object valueObj) {
1953 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1956 if (valueObj instanceof List) {
1957 return ((List) valueObj).size() > 1;
1962 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1963 if (valueObj instanceof List) {
1964 return ((List) valueObj).size() > 1;
1970 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1971 if (propertyValue == null) {
1974 // skip not relevant for Tosca property
1975 if ("dependencies".equals(property.getName())) {
1978 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1981 if (javaBean instanceof ToscaPropertyConstraint) {
1982 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1984 removeDefaultP(propertyValue);
1985 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1986 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1987 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1989 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1992 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1993 final Tag customTag) {
1994 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1995 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1996 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1999 private void removeDefaultP(final Object propertyValue) {
2000 if (propertyValue instanceof Map) {
2001 final Map mapPropertyValue = ((Map) propertyValue);
2002 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
2003 Object defaultValue = null;
2004 while (iter.hasNext()) {
2005 final Map.Entry entry = iter.next();
2006 if ("_defaultp_".equals(entry.getKey())) {
2007 defaultValue = entry.getValue();
2009 } else if (entry.getValue() instanceof Map) {
2010 removeDefaultP(entry.getValue());
2013 if (defaultValue != null) {
2014 mapPropertyValue.putIfAbsent("default", defaultValue);
2020 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
2021 // remove the bean type from the output yaml (!! ...)
2022 if (!classTags.containsKey(javaBean.getClass())) {
2023 addClassTag(javaBean.getClass(), Tag.MAP);
2025 return super.representJavaBean(properties, javaBean);
2028 private class RepresentToscaAttribute implements Represent {
2031 public Node representData(Object data) {
2032 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
2033 return represent(toscaAttribute.asToscaMap());
2037 private class RepresentToscaPropertyAssignment implements Represent {
2039 public Node representData(Object data) {
2040 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
2041 if (toscaOperationAssignment.getValue() instanceof String) {
2042 final String stringValue = (String) toscaOperationAssignment.getValue();
2043 if (isPropertyOrAttributeFunction(stringValue)) {
2044 return representGetAttribute(stringValue);
2046 return representScalar(Tag.STR, stringValue);
2048 return represent(null);
2051 public Node representGetAttribute(final String getAttributeFunction) {
2052 return represent(new Yaml().load(getAttributeFunction));
2055 public boolean isPropertyOrAttributeFunction(final String value) {
2057 final Yaml yaml = new Yaml();
2058 final Object yamlObj = yaml.load(value);
2059 if (!(yamlObj instanceof Map)) {
2062 final Map<String, Object> getAttributeMap = (Map) yamlObj;
2063 if (getAttributeMap.size() != 1) {
2066 final List<String> functionList = Arrays
2067 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2068 final Optional<String> function = getAttributeMap.keySet().stream()
2069 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2070 if (function.isEmpty()) {
2073 final String functionName = function.get();
2074 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2075 if (GET_INPUT.getFunctionName().equals(functionName)) {
2076 return validateGetInputValue(getAttributeValueObj);
2078 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2080 } catch (final Exception ignored) {
2086 private class RepresentNull implements Represent {
2089 public Node representData(Object data) {
2090 // possible values are here http://yaml.org/type/null.html
2091 return representScalar(Tag.NULL, "");
2096 private static class UnsortedPropertyUtils extends PropertyUtils {
2099 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2100 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2101 return new LinkedHashSet<>(fields);