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 && !isSkipImports) {
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);
813 setImports(imports, dependencies, fetchedComponent);
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) {
848 componentsList.forEach(component -> setImports(imports, dependencies, component));
851 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
852 final Component component) {
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 addImports(imports, keyNameBuilder, files);
864 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
865 if (!ModelConverter.isAtomicComponent(component)) {
866 final Map<String, String> interfaceFiles = new HashMap<>();
867 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
868 keyNameBuilder.append("-interface");
869 addImports(imports, keyNameBuilder, interfaceFiles);
875 * Adds the found resource to the import definition list.
877 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
878 final Map<String, String> files) {
879 final String mapKey = keyNameBuilder.toString();
880 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
881 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
882 importsListMember.put(keyNameBuilder.toString(), files);
883 imports.add(importsListMember);
887 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
888 Map<String, ToscaNodeType> nodeTypes) {
889 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
892 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
893 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
894 boolean isAssociatedComponent) {
895 log.debug("start convert node type for {}", component.getUniqueId());
896 ToscaNodeType toscaNodeType = createNodeType(component);
897 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
898 .getAllInterfaceLifecycleTypes(component.getModel());
899 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
900 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
901 return Either.right(ToscaError.GENERAL_ERROR);
903 if (lifecycleTypeEither.isLeft()) {
904 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
905 .collect(Collectors.toList());
906 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
908 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
909 if (dataTypesEither.isRight()) {
910 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
911 return Either.right(ToscaError.GENERAL_ERROR);
913 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
914 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
915 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
916 if (!toscaAttributeMap.isEmpty()) {
917 toscaNodeType.setAttributes(toscaAttributeMap);
919 Map<String, ToscaProperty> convertedProperties = new HashMap();
920 if (CollectionUtils.isNotEmpty(component.getProperties())) {
921 List<PropertyDefinition> properties = component.getProperties();
922 convertedProperties = properties.stream()
923 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
924 .toMap(PropertyDataDefinition::getName,
925 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
927 if (MapUtils.isNotEmpty(convertedProperties)) {
928 toscaNodeType.setProperties(convertedProperties);
930 /* convert private data_types */
931 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
932 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
933 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
934 for (DataTypeDefinition dataType : privateDataTypes) {
935 log.debug("Emitting private data type: component.name={} dataType.name={}",
936 component.getNormalizedName(), dataType.getName());
937 ToscaDataType toscaDataType = new ToscaDataType();
938 toscaDataType.setDerived_from(dataType.getDerivedFromName());
939 toscaDataType.setDescription(dataType.getDescription());
940 toscaDataType.setVersion(dataType.getVersion());
941 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
942 toscaDataType.setProperties(dataType.getProperties().stream()
943 .collect(Collectors.toMap(
944 PropertyDataDefinition::getName,
945 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
946 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
950 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
952 toscaNode.setData_types(toscaDataTypeMap);
955 // Extracted to method for code reuse
956 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
959 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
960 final ToscaProperty toscaProperty) {
961 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
962 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
963 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
966 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
967 final Map<String, DataTypeDefinition> dataTypes) {
968 if (CollectionUtils.isEmpty(attributeList)) {
969 return Collections.emptyMap();
971 final AttributeConverter converter = new AttributeConverter(dataTypes);
972 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
973 for (final AttributeDefinition attributeDefinition : attributeList) {
974 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
976 return toscaAttributeMap;
979 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
980 Component component, ToscaTemplate toscaNode,
981 Map<String, ToscaNodeType> nodeTypes,
982 ToscaNodeType toscaNodeType,
983 Map<String, DataTypeDefinition> dataTypes) {
984 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
986 if (capabilities.isRight()) {
987 return Either.right(capabilities.right().value());
989 toscaNodeType = capabilities.left().value();
990 log.debug("Capabilities converted for {}", component.getUniqueId());
992 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
993 .convertRequirements(componentsCache, component, toscaNodeType);
994 if (requirements.isRight()) {
995 return Either.right(requirements.right().value());
997 toscaNodeType = requirements.left().value();
998 log.debug("Requirements converted for {}", component.getUniqueId());
1000 String toscaResourceName;
1001 switch (component.getComponentType()) {
1003 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
1004 .getMetadataDataDefinition()).getToscaResourceName();
1007 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
1008 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
1011 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
1012 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1015 nodeTypes.put(toscaResourceName, toscaNodeType);
1016 toscaNode.setNode_types(nodeTypes);
1017 log.debug("finish convert node type for {}", component.getUniqueId());
1018 return Either.left(toscaNode);
1021 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
1022 final Map<String, Component> componentCache,
1023 final Map<String, DataTypeDefinition> dataTypes,
1024 final ToscaTopolgyTemplate topologyTemplate) {
1026 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
1027 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
1028 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
1029 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
1030 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
1032 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
1033 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1034 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
1036 Map<String, ToscaGroupTemplate> groupsMap = null;
1037 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
1038 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
1039 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
1040 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
1042 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
1043 List<Object> occur = new ArrayList<>();
1044 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
1045 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
1046 nodeTemplate.setOccurrences(occur);
1048 if (componentInstance.getInstanceCount() != null) {
1049 ObjectMapper objectMapper = new ObjectMapper();
1050 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
1052 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
1053 nodeTemplate.setInstance_count(map);
1056 nodeTemplate.setType(componentInstance.getToscaComponentName());
1057 nodeTemplate.setDirectives(componentInstance.getDirectives());
1058 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
1059 if (nodeFilter != null && nodeFilter.hasData()) {
1060 nodeTemplate.setNode_filter(nodeFilter);
1062 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
1063 .getOriginComponent(componentCache, componentInstance);
1064 if (originComponentRes.isRight()) {
1065 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1068 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
1069 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
1070 if (requirements.isRight()) {
1071 convertNodeTemplatesRes = Either.right(requirements.right().value());
1074 final String instanceUniqueId = componentInstance.getUniqueId();
1075 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1077 nodeTemplate = requirements.left().value();
1079 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1081 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1082 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1083 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1085 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1088 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1089 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1090 if (capabilities.isRight()) {
1091 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1094 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1096 nodeTemplate = capabilities.left().value();
1097 final Map<String, Object> props = new HashMap<>();
1098 final Map<String, Object> attribs = new HashMap<>();
1100 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1101 // Adds the properties of parent component to map
1102 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1103 addAttributesOfParentComponent(originalComponent, attribs);
1106 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1107 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1109 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1110 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1113 if (componentInstancesInputs != null
1114 && componentInstancesInputs.containsKey(instanceUniqueId)
1115 && !isComponentOfTypeServiceProxy(componentInstance)) {
1116 //For service proxy the inputs are already handled under instance properties above
1117 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1120 //M3[00001] - NODE TEMPLATE INTERFACES - START
1121 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1122 //M3[00001] - NODE TEMPLATE INTERFACES - END
1123 if (MapUtils.isNotEmpty(props)) {
1124 nodeTemplate.setProperties(props);
1126 if (MapUtils.isNotEmpty(attribs)) {
1127 nodeTemplate.setAttributes(attribs);
1130 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1131 if (CollectionUtils.isNotEmpty(groupInstances)) {
1132 if (groupsMap == null) {
1133 groupsMap = new HashMap<>();
1135 for (final GroupInstance groupInst : groupInstances) {
1136 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1137 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1142 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1144 if (groupsMap != null) {
1145 log.debug("instance groups added");
1146 topologyTemplate.addGroups(groupsMap);
1148 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1149 ((Service) component).getForwardingPaths())) {
1150 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1151 ForwardingPathToscaUtil
1152 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1153 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1155 if (convertNodeTemplatesRes == null) {
1156 convertNodeTemplatesRes = Either.left(nodeTemplates);
1158 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1159 return convertNodeTemplatesRes;
1162 private Object convertToToscaObject(String value) {
1164 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1165 StringReader reader = new StringReader(value);
1166 JsonReader jsonReader = new JsonReader(reader);
1167 jsonReader.setLenient(true);
1168 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1169 if (jsonElement.isJsonObject()) {
1170 JsonObject jsonObj = jsonElement.getAsJsonObject();
1171 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1172 return mapConverterInst.handleComplexJsonValue(jsonElement);
1176 } catch (Exception e) {
1177 log.debug("convertToToscaValue failed to parse json value :", e);
1182 private Object parseToIntIfPossible(final String value) {
1183 final Integer intValue = Ints.tryParse(value);
1184 return intValue == null ? value : intValue;
1187 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1188 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1189 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1191 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1192 nodeTemplate.setInterfaces(null);
1196 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1198 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1199 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1201 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1202 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1204 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1205 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1208 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1209 return Objects.nonNull(componentInstance.getOriginType())
1210 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1213 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1214 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1215 String instanceUniqueId, Map<String, Object> props) {
1217 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1218 if (instanceInputsList != null) {
1219 instanceInputsList.forEach(input -> {
1220 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1221 : input.getDefaultValue();
1222 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1227 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1228 final Map<String, DataTypeDefinition> dataTypes,
1229 final String instanceUniqueId,
1230 final Map<String, Object> props) {
1232 if (isNotEmpty(componentInstancesProperties)) {
1233 componentInstancesProperties.get(instanceUniqueId)
1234 // Converts and adds each value to property map
1235 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1239 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1240 final String instanceUniqueId,
1241 final Map<String, Object> attribs) {
1243 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1244 componentInstancesAttributes.get(instanceUniqueId)
1245 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1249 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1250 Component componentOfInstance, Map<String, Object> props) {
1252 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1253 if (isNotEmpty(componentProperties)) {
1254 componentProperties.stream()
1255 // Filters out properties with empty default values
1256 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1257 // Converts and adds each value to property map
1258 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1262 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1264 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1265 if (isNotEmpty(componentAttributes)) {
1266 componentAttributes.stream()
1267 // Filters out Attributes with empty default values
1268 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1269 // Converts and adds each value to attribute map
1270 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1274 private ToscaNodeType createNodeType(Component component) {
1275 ToscaNodeType toscaNodeType = new ToscaNodeType();
1276 if (ModelConverter.isAtomicComponent(component)) {
1277 if (((Resource) component).getDerivedFrom() != null) {
1278 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1280 toscaNodeType.setDescription(component.getDescription());
1282 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1284 toscaNodeType.setDerived_from(derivedFrom);
1286 return toscaNodeType;
1289 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1291 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1292 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1293 List<ComponentInstance> componentInstances = container.getComponentInstances();
1294 if (CollectionUtils.isEmpty(componentInstances)) {
1297 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1298 componentInstances.stream()
1299 .filter(this::isComponentOfTypeServiceProxy)
1300 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1301 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1304 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1305 Component serviceComponent;
1306 ComponentParametersView componentParametersView = new ComponentParametersView();
1307 componentParametersView.disableAll();
1308 componentParametersView.setIgnoreInterfaces(false);
1309 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1310 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1311 if (service.isRight()) {
1312 log.debug("Failed to fetch original service component with id {} for instance {}",
1313 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1314 return Either.right(ToscaError.GENERAL_ERROR);
1316 serviceComponent = service.left().value();
1319 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1320 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1321 if (lifecycleTypeEither.isRight()) {
1322 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1323 return Either.right(ToscaError.GENERAL_ERROR);
1326 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1327 .map(InterfaceDataDefinition::getType)
1328 .collect(Collectors.toList());
1329 //Add interface types for local interfaces in the original service component for proxy
1330 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1331 allGlobalInterfaceTypes);
1332 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1333 proxyInterfaceTypes.putAll(localInterfaceTypes);
1337 return Either.left(proxyInterfaceTypes);
1340 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1341 Component container) {
1343 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1344 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1346 List<ComponentInstance> componentInstances = container.getComponentInstances();
1348 if (componentInstances == null || componentInstances.isEmpty()) {
1351 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1352 List<ComponentInstance> proxyInst = componentInstances.stream()
1353 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1354 .collect(Collectors.toList());
1355 if (proxyInst != null && !proxyInst.isEmpty()) {
1356 for (ComponentInstance inst : proxyInst) {
1357 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1361 if (serviceProxyInstanceList.isEmpty()) {
1364 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1365 .getLatestByName("serviceProxy", null);
1366 if (serviceProxyOrigin.isRight()) {
1367 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1368 serviceProxyOrigin.right().value());
1369 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1371 Component origComponent = serviceProxyOrigin.left().value();
1373 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1374 Component serviceComponent = null;
1375 ComponentParametersView componentParametersView = new ComponentParametersView();
1376 componentParametersView.disableAll();
1377 componentParametersView.setIgnoreCategories(false);
1378 componentParametersView.setIgnoreProperties(false);
1379 componentParametersView.setIgnoreInputs(false);
1380 componentParametersView.setIgnoreInterfaces(false);
1381 componentParametersView.setIgnoreRequirements(false);
1382 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1383 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1384 if (service.isRight()) {
1385 log.debug("Failed to fetch resource with id {} for instance {}",
1386 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1388 serviceComponent = service.left().value();
1391 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1392 entryProxy.getValue());
1393 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1396 return Either.left(nodeTypesMap);
1399 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1400 final Component container, final ToscaTemplate toscaNode) {
1401 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1403 if (CollectionUtils.isEmpty(componentInstances)) {
1406 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1407 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1408 .collect(Collectors.toList());
1409 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1410 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1411 final Map<String, ToscaNodeType> nodeTypes =
1412 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1413 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1419 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1420 Component proxyComponent, ComponentInstance componentInstance) {
1421 ToscaNodeType toscaNodeType = new ToscaNodeType();
1422 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1424 toscaNodeType.setDerived_from(derivedFrom);
1425 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1426 origComponent.getModel());
1427 if (dataTypesEither.isRight()) {
1428 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1430 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1431 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1432 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1434 if (MapUtils.isNotEmpty(capabilities)) {
1435 toscaNodeType.setCapabilities(capabilities);
1437 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1438 .convertProxyRequirements(componentCache, componentInstance);
1439 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1440 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1442 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1443 proxyProperties.ifPresent(toscaNodeType::setProperties);
1445 Map<String, Object> interfaceMap = new HashMap<>();
1446 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1447 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1448 if (proxyInterfaces.isPresent()) {
1449 interfaceMap = proxyInterfaces.get();
1452 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1455 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1456 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1458 return toscaNodeType;
1461 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1462 ComponentInstance componentInstance,
1463 List<RequirementCapabilityRelDef> relations,
1464 ToscaNodeTemplate nodeTypeTemplate,
1465 Component originComponent,
1466 Map<String, Component> componentCache) {
1468 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1470 if (isNotEmpty(requirementDefinitionList)) {
1472 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1473 requirementDefinitionList, originComponent, componentCache);
1474 if (CollectionUtils.isNotEmpty(toscaRequirements)) {
1475 nodeTypeTemplate.setRequirements(toscaRequirements);
1477 } catch (final Exception e) {
1478 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1479 componentInstance.getName(), e);
1480 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1483 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1484 return Either.left(nodeTypeTemplate);
1487 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1488 final ComponentInstance componentInstance,
1489 final List<RequirementCapabilityRelDef> filteredRelations,
1490 final Component originComponent,
1491 final Map<String, Component> componentCache)
1492 throws ToscaExportException {
1494 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1495 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1496 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1497 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1498 if (MapUtils.isNotEmpty(toscaTemplateRequirementMap)) {
1499 toscaRequirements.add(toscaTemplateRequirementMap);
1503 return toscaRequirements;
1506 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1507 List<RequirementCapabilityRelDef> relations) {
1508 return relations.stream()
1509 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1512 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1513 final Component fromOriginComponent,
1514 final List<ComponentInstance> instancesList,
1515 final RequirementCapabilityRelDef relationshipDefinition,
1516 final Map<String, Component> componentCache)
1517 throws ToscaExportException {
1519 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1520 if (MapUtils.isEmpty(reqMap)) {
1521 return new HashMap<>();
1523 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition.getRelationships().get(0);
1524 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1526 final ComponentInstance toInstance = instancesList.stream().filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1527 .findFirst().orElse(null);
1528 if (toInstance == null) {
1529 final String errorMsg = String
1530 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1531 relationshipDefinition.getToNode());
1532 log.debug(errorMsg);
1533 throw new ToscaExportException(errorMsg);
1535 final Optional<RequirementDefinition> reqOpt = findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1536 if (reqOpt.isEmpty()) {
1537 final String errorMsg = String.format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1538 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1539 log.debug(errorMsg);
1540 throw new ToscaExportException(errorMsg);
1542 final ComponentParametersView filter = new ComponentParametersView(true);
1543 filter.setIgnoreComponentInstances(false);
1544 filter.setIgnoreCapabilities(false);
1545 filter.setIgnoreGroups(false);
1546 final Either<Component, StorageOperationStatus> getOriginRes =
1547 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1548 if (getOriginRes.isRight()) {
1549 final String errorMsg = String.format(
1550 "Failed to build substituted name for the requirement %s. Failed to get an origin component with uniqueId %s",
1551 reqOpt.get().getName(), toInstance.getActualComponentUid());
1552 log.debug(errorMsg);
1553 throw new ToscaExportException(errorMsg);
1555 final Component toOriginComponent = getOriginRes.left().value();
1556 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1557 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1558 if (capOpt.isEmpty()) {
1559 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1560 if (capOpt.isEmpty()) {
1561 final String errorMsg = String.format("Failed to find a capability with name %s on a component with uniqueId %s",
1562 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1563 log.debug(errorMsg);
1564 throw new ToscaExportException(errorMsg);
1567 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1568 capabilityRequirementRelationship, toInstance, componentCache);
1571 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1572 CapabilityDefinition capability) {
1573 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1574 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1577 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1578 Component toOriginComponent, Component fromOriginComponent,
1579 RequirementDefinition requirement) {
1580 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1581 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1582 if (cap.isEmpty()) {
1583 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1584 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1589 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1590 final Component toOriginComponent,
1591 final CapabilityDefinition capability,
1592 final RequirementDefinition requirement,
1593 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1594 final ComponentInstance toInstance,
1595 final Map<String, Component> componentCache)
1596 throws ToscaExportException {
1598 List<String> reducedPath = capability.getPath();
1599 if (capability.getOwnerId() != null) {
1600 reducedPath = capabilityRequirementConverter
1601 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1603 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1604 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1605 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1606 if (capabilityNameEither.isRight()) {
1607 final String errorMsg = String.format(
1608 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1609 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1612 throw new ToscaExportException(errorMsg);
1614 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1615 .buildSubstitutedName(componentCache, fromOriginComponent,
1616 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1617 if (requirementNameEither.isRight()) {
1618 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1619 + "with name %s on a component with uniqueId %s",
1620 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1621 log.debug(errorMsg);
1622 throw new ToscaExportException(errorMsg);
1624 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1625 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1626 toscaRequirement.setNode(toInstance.getName());
1627 toscaRequirement.setCapability(capabilityNameEither.left().value());
1628 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1629 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1631 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1635 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1636 Map<String, List<RequirementDefinition>> reqMap,
1637 RelationshipInfo reqAndRelationshipPair,
1638 String fromInstanceId) {
1639 for (final List<RequirementDefinition> reqList : reqMap.values()) {
1640 final Optional<RequirementDefinition> reqOpt = reqList.stream()
1641 .filter(r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)).findFirst();
1642 if (reqOpt.isPresent()) {
1646 return Optional.empty();
1650 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1651 * 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
1652 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1654 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1655 RequirementDefinition requirement, String fromInstanceId) {
1656 if (originComponent.isService() && requirement.getUniqueId().equals(reqAndRelationshipPair.getRequirementUid())) {
1659 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1660 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1661 reqAndRelationshipPair.getRequirement());
1664 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1668 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1669 Component originComponent) {
1670 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1671 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1672 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1675 private boolean isCvfc(Component component) {
1676 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1679 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1680 final Map<String, Component> componentCache) {
1681 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1682 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1683 if (toscaCapabilitiesRes.isRight()) {
1684 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1685 return Either.right(toscaCapabilitiesRes.right().value());
1687 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1688 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1689 return Either.left(toscaCapabilitiesRes.left().value());
1691 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1693 return Either.left(Collections.emptyMap());
1696 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1697 Map<String, DataTypeDefinition> dataTypes) {
1698 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1699 if (!toscaCapabilities.isEmpty()) {
1700 nodeType.setCapabilities(toscaCapabilities);
1702 log.debug("Finish convert Capabilities for node type");
1703 return Either.left(nodeType);
1706 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1707 if (artifacts == null) {
1710 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1711 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1712 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1713 artifact.setFile(entry.getValue().getFile());
1714 artifact.setType(entry.getValue().getType());
1715 artifact.setProperties(entry.getValue().getProperties());
1716 arts.put(entry.getKey(), artifact);
1721 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1722 if (inNodeFilter == null) {
1725 NodeFilter nodeFilter = new NodeFilter();
1726 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1727 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1728 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1729 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1730 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1731 nodeFilter.setCapabilities(capabilitiesCopy);
1733 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1734 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1735 nodeFilter.setProperties(propertiesCopy);
1737 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1738 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1741 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1742 if (substitutionFilterDataDefinition == null) {
1745 NodeFilter nodeFilter = new NodeFilter();
1746 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1747 if (!propertiesCopy.isEmpty()) {
1748 nodeFilter.setProperties(propertiesCopy);
1750 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1751 return cloneObjectFromYml(nodeFilter, NodeFilter.class);
1754 private Object cloneToscaId(Object toscaId) {
1755 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1758 private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
1759 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1760 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1763 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1764 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1765 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1769 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1770 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1771 final var capabilityFilter = new CapabilityFilter();
1772 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1773 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1774 capabilitiesCopy.add(capabilityFilterCopyMap);
1778 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1779 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1780 return Collections.emptyList();
1782 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1783 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1784 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1785 final String propertyName = propertyFilter.getName();
1786 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1787 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1788 if (constraints == null) {
1789 constraints = new ArrayList<>();
1791 constraints.add(buildNodeFilterValue(filterConstraint));
1796 propertyFilterDefinitionMap.entrySet().stream()
1797 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1798 .forEach(propertiesCopy::add);
1799 return propertiesCopy;
1802 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1803 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1805 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1806 return Collections.emptyList();
1808 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1809 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1810 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1811 final String propertyName = propertyFilter.getName();
1812 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1813 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1814 if (constraints == null) {
1815 constraints = new ArrayList<>();
1817 constraints.add(buildNodeFilterValue(filterConstraint));
1822 propertyFilterDefinitionMap.entrySet().stream()
1823 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1824 .forEach(propertiesCopy::add);
1825 return propertiesCopy;
1828 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1829 if (filterConstraint.getValue() instanceof ToscaFunction) {
1830 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1832 if (filterConstraint.getValue() instanceof List) {
1833 if (((List<?>) filterConstraint.getValue()).get(0) instanceof ToscaFunction) {
1834 List<Object> toscaFunctionList = new ArrayList<>();
1835 ((List<?>) filterConstraint.getValue()).forEach(toscaFunctionValue -> toscaFunctionList.add(
1836 ((ToscaFunction) toscaFunctionValue).getJsonObjectValue()));
1837 return Map.of(filterConstraint.getOperator().getType(), toscaFunctionList);
1840 if (doesTypeNeedConvertingToIntOrFloat(filterConstraint.getOriginalType(), filterConstraint.getValue())) {
1841 ToscaType toscaType = ToscaType.getToscaType(
1842 filterConstraint.getValue() instanceof List ? ToscaType.LIST.getType() : filterConstraint.getOriginalType());
1843 filterConstraint.setValue(toscaType.convert(String.valueOf(filterConstraint.getValue())));
1844 } else if (ConstraintType.LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1845 ConstraintType.MIN_LENGTH.getType().equals(filterConstraint.getOperator().getType()) ||
1846 ConstraintType.MAX_LENGTH.getType().equals(filterConstraint.getOperator().getType())) {
1847 filterConstraint.setValue(Integer.valueOf(String.valueOf(filterConstraint.getValue())));
1849 if (doesTypeNeedConvertingToBoolean(filterConstraint.getOriginalType())) {
1850 filterConstraint.setValue(ToscaType.getToscaType(filterConstraint.getOriginalType()).convert(
1851 String.valueOf(filterConstraint.getValue())));
1853 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1856 private static boolean doesTypeNeedConvertingToIntOrFloat(String propertyType, Object value) {
1857 if (value instanceof List && ((List<?>) value).get(0) instanceof LinkedHashMap
1858 && ((LinkedHashMap) ((List<?>) value).get(0)).get("type") != null) {
1861 return ToscaType.INTEGER.getType().equals(propertyType) || ToscaType.FLOAT.getType().equals(propertyType);
1864 private static boolean doesTypeNeedConvertingToBoolean(String propertyType) {
1865 return ToscaType.BOOLEAN.getType().equals(propertyType);
1868 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1869 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1870 return Collections.emptyMap();
1872 Map<String, String[]> propertyMapping = new HashMap<>();
1873 List<InputDefinition> propertyMappedInputList = component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).collect(
1874 Collectors.toList());
1876 if (CollectionUtils.isNotEmpty(propertyMappedInputList)) {
1877 propertyMappedInputList.forEach(inputDefinition -> {
1878 if (StringUtils.isNotEmpty(inputDefinition.getPropertyId())) {
1879 Optional<PropertyDefinition> property = component.getProperties().stream()
1880 .filter(propertyDefinition -> propertyDefinition.getUniqueId().equals(inputDefinition.getPropertyId())).findFirst();
1881 if (property.isPresent()) {
1882 propertyMapping.put(property.get().getName(), new String[]{inputDefinition.getName()});
1885 propertyMapping.put(inputDefinition.getName(), new String[]{inputDefinition.getName()});
1889 return propertyMapping;
1892 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1893 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1894 return Collections.emptyMap();
1896 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1897 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1900 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1901 if (Objects.isNull(proxyComponent)) {
1902 return Optional.empty();
1904 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1905 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1906 proxyProperties.putAll(proxyComponent.getProperties().stream()
1907 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1908 .toMap(PropertyDataDefinition::getName,
1909 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1911 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1914 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1915 String componentUniqueId) {
1916 if (CollectionUtils.isEmpty(componentInputs)) {
1917 return new HashMap<>();
1919 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1920 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1923 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1924 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1925 return Optional.empty();
1927 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1928 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1930 // always available in the proxy node template
1931 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1932 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1935 private Configuration getConfiguration() {
1936 return ConfigurationManager.getConfigurationManager().getConfiguration();
1939 private static class CustomRepresenter extends Representer {
1941 CustomRepresenter() {
1942 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1943 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1944 // null representer is exceptional and it is stored as an instance
1947 this.nullRepresenter = new RepresentNull();
1950 public boolean validateGetInputValue(final Object valueObj) {
1951 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1954 if (valueObj instanceof List) {
1955 return ((List) valueObj).size() > 1;
1960 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1961 if (valueObj instanceof List) {
1962 return ((List) valueObj).size() > 1;
1968 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1969 if (propertyValue == null) {
1972 // skip not relevant for Tosca property
1973 if ("dependencies".equals(property.getName())) {
1976 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1979 if (javaBean instanceof ToscaPropertyConstraint) {
1980 return handleToscaPropertyConstraint((ToscaPropertyConstraint) javaBean, property, propertyValue, customTag);
1982 removeDefaultP(propertyValue);
1983 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1984 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1985 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1987 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1990 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1991 final Tag customTag) {
1992 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1993 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1994 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1997 private void removeDefaultP(final Object propertyValue) {
1998 if (propertyValue instanceof Map) {
1999 final Map mapPropertyValue = ((Map) propertyValue);
2000 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
2001 Object defaultValue = null;
2002 while (iter.hasNext()) {
2003 final Map.Entry entry = iter.next();
2004 if ("_defaultp_".equals(entry.getKey())) {
2005 defaultValue = entry.getValue();
2007 } else if (entry.getValue() instanceof Map) {
2008 removeDefaultP(entry.getValue());
2011 if (defaultValue != null) {
2012 mapPropertyValue.putIfAbsent("default", defaultValue);
2018 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
2019 // remove the bean type from the output yaml (!! ...)
2020 if (!classTags.containsKey(javaBean.getClass())) {
2021 addClassTag(javaBean.getClass(), Tag.MAP);
2023 return super.representJavaBean(properties, javaBean);
2026 private class RepresentToscaAttribute implements Represent {
2029 public Node representData(Object data) {
2030 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
2031 return represent(toscaAttribute.asToscaMap());
2035 private class RepresentToscaPropertyAssignment implements Represent {
2037 public Node representData(Object data) {
2038 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
2039 if (toscaOperationAssignment.getValue() instanceof String) {
2040 final String stringValue = (String) toscaOperationAssignment.getValue();
2041 if (isPropertyOrAttributeFunction(stringValue)) {
2042 return representGetAttribute(stringValue);
2044 return representScalar(Tag.STR, stringValue);
2046 return represent(null);
2049 public Node representGetAttribute(final String getAttributeFunction) {
2050 return represent(new Yaml().load(getAttributeFunction));
2053 public boolean isPropertyOrAttributeFunction(final String value) {
2055 final Yaml yaml = new Yaml();
2056 final Object yamlObj = yaml.load(value);
2057 if (!(yamlObj instanceof Map)) {
2060 final Map<String, Object> getAttributeMap = (Map) yamlObj;
2061 if (getAttributeMap.size() != 1) {
2064 final List<String> functionList = Arrays
2065 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
2066 final Optional<String> function = getAttributeMap.keySet().stream()
2067 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
2068 if (function.isEmpty()) {
2071 final String functionName = function.get();
2072 final Object getAttributeValueObj = getAttributeMap.get(functionName);
2073 if (GET_INPUT.getFunctionName().equals(functionName)) {
2074 return validateGetInputValue(getAttributeValueObj);
2076 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
2078 } catch (final Exception ignored) {
2084 private class RepresentNull implements Represent {
2087 public Node representData(Object data) {
2088 // possible values are here http://yaml.org/type/null.html
2089 return representScalar(Tag.NULL, "");
2094 private static class UnsortedPropertyUtils extends PropertyUtils {
2097 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
2098 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
2099 return new LinkedHashSet<>(fields);