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.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement;
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 fj.data.Either;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.LinkedHashMap;
38 import java.util.LinkedHashSet;
39 import java.util.List;
41 import java.util.Map.Entry;
42 import java.util.Objects;
43 import java.util.Optional;
45 import java.util.function.Supplier;
46 import java.util.stream.Collectors;
47 import lombok.NoArgsConstructor;
48 import org.apache.commons.collections.CollectionUtils;
49 import org.apache.commons.collections.MapUtils;
50 import org.apache.commons.io.FilenameUtils;
51 import org.apache.commons.lang3.StringUtils;
52 import org.apache.commons.lang3.tuple.ImmutablePair;
53 import org.apache.commons.lang3.tuple.ImmutableTriple;
54 import org.apache.commons.lang3.tuple.Triple;
55 import org.onap.sdc.tosca.services.YamlUtil;
56 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
57 import org.openecomp.sdc.be.config.Configuration;
58 import org.openecomp.sdc.be.config.ConfigurationManager;
59 import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
60 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
61 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
62 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
70 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
71 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
73 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
74 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
75 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
76 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
77 import org.openecomp.sdc.be.exception.ToscaExportException;
78 import org.openecomp.sdc.be.model.ArtifactDefinition;
79 import org.openecomp.sdc.be.model.AttributeDefinition;
80 import org.openecomp.sdc.be.model.CapabilityDefinition;
81 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
82 import org.openecomp.sdc.be.model.Component;
83 import org.openecomp.sdc.be.model.ComponentInstance;
84 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
85 import org.openecomp.sdc.be.model.ComponentInstanceInput;
86 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
87 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
88 import org.openecomp.sdc.be.model.ComponentParametersView;
89 import org.openecomp.sdc.be.model.DataTypeDefinition;
90 import org.openecomp.sdc.be.model.GroupInstance;
91 import org.openecomp.sdc.be.model.InputDefinition;
92 import org.openecomp.sdc.be.model.InterfaceDefinition;
93 import org.openecomp.sdc.be.model.PropertyDefinition;
94 import org.openecomp.sdc.be.model.RelationshipInfo;
95 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
96 import org.openecomp.sdc.be.model.RequirementDefinition;
97 import org.openecomp.sdc.be.model.Resource;
98 import org.openecomp.sdc.be.model.Service;
99 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
100 import org.openecomp.sdc.be.model.category.CategoryDefinition;
101 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
102 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
103 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
104 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
105 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
106 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
107 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
108 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
109 import org.openecomp.sdc.be.tosca.model.NodeFilter;
110 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
111 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
112 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
113 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
114 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
115 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
116 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
117 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
118 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
119 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
120 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
121 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
122 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
123 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
124 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
125 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
126 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
127 import org.openecomp.sdc.be.tosca.utils.InputConverter;
128 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
129 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
130 import org.openecomp.sdc.common.log.wrappers.Logger;
131 import org.springframework.beans.factory.annotation.Autowired;
132 import org.yaml.snakeyaml.DumperOptions;
133 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
134 import org.yaml.snakeyaml.Yaml;
135 import org.yaml.snakeyaml.introspector.BeanAccess;
136 import org.yaml.snakeyaml.introspector.Property;
137 import org.yaml.snakeyaml.introspector.PropertyUtils;
138 import org.yaml.snakeyaml.nodes.MappingNode;
139 import org.yaml.snakeyaml.nodes.Node;
140 import org.yaml.snakeyaml.nodes.NodeTuple;
141 import org.yaml.snakeyaml.nodes.Tag;
142 import org.yaml.snakeyaml.representer.Represent;
143 import org.yaml.snakeyaml.representer.Representer;
146 @org.springframework.stereotype.Component("tosca-export-handler")
147 public class ToscaExportHandler {
149 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
150 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
151 private static final String INVARIANT_UUID = "invariantUUID";
152 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
153 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
154 private static final String IMPORTS_FILE_KEY = "file";
155 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
156 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
157 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
158 private static final String NATIVE_ROOT = "tosca.nodes.Root";
159 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
160 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
161 private static final YamlUtil yamlUtil = new YamlUtil();
162 private static final String COULD_NOT_PARSE_COMPONENT_ATTRIBUTES_COMPONENT_UNIQUE_ID = "Could not parse component '{}' attributes. Component unique id '{}'.";
163 private ApplicationDataTypeCache applicationDataTypeCache;
164 private ToscaOperationFacade toscaOperationFacade;
165 private CapabilityRequirementConverter capabilityRequirementConverter;
166 private PolicyExportParser policyExportParser;
167 private GroupExportParser groupExportParser;
168 private PropertyConvertor propertyConvertor;
169 private AttributeConverter attributeConverter;
170 private InputConverter inputConverter;
171 private OutputConverter outputConverter;
172 private InterfaceLifecycleOperation interfaceLifecycleOperation;
173 private InterfacesOperationsConverter interfacesOperationsConverter;
174 private ToscaModelImportCassandraDao toscaModelImportCassandraDao;
177 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
178 final ToscaOperationFacade toscaOperationFacade,
179 final CapabilityRequirementConverter capabilityRequirementConverter,
180 final PolicyExportParser policyExportParser,
181 final GroupExportParser groupExportParser,
182 final PropertyConvertor propertyConvertor,
183 final AttributeConverter attributeConverter,
184 final InputConverter inputConverter,
185 final OutputConverter outputConverter,
186 final InterfaceLifecycleOperation interfaceLifecycleOperation,
187 final InterfacesOperationsConverter interfacesOperationsConverter,
188 final ToscaModelImportCassandraDao toscaModelImportCassandraDao) {
189 this.applicationDataTypeCache = applicationDataTypeCache;
190 this.toscaOperationFacade = toscaOperationFacade;
191 this.capabilityRequirementConverter = capabilityRequirementConverter;
192 this.policyExportParser = policyExportParser;
193 this.groupExportParser = groupExportParser;
194 this.propertyConvertor = propertyConvertor;
195 this.attributeConverter = attributeConverter;
196 this.inputConverter = inputConverter;
197 this.outputConverter = outputConverter;
198 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
199 this.interfacesOperationsConverter = interfacesOperationsConverter;
200 this.toscaModelImportCassandraDao = toscaModelImportCassandraDao;
203 public static String getInterfaceFilename(String artifactName) {
204 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
207 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
208 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
211 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
212 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
215 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
216 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
219 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
220 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
221 if (CollectionUtils.isEmpty(imports)) {
222 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
223 return Either.right(ToscaError.GENERAL_ERROR);
225 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
226 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
227 .startsWith("org.openecomp.resource.abstract.nodes.")) {
228 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
229 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(), component.getModel());
230 if (baseType.isLeft() && baseType.left().value() != null) {
231 addDependencies(imports, dependencies, baseType.left().value());
233 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
237 String toscaVersion = null;
238 if (component instanceof Resource) {
239 toscaVersion = ((Resource) component).getToscaVersion();
241 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
242 toscaTemplate.setImports(imports);
243 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
244 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
245 isAssociatedComponent);
246 if (toscaTemplateRes.isRight()) {
247 return Either.right(toscaTemplateRes.right().value());
249 toscaTemplate = toscaTemplateRes.left().value();
250 toscaTemplate.setDependencies(dependencies);
251 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
252 return Either.left(toscaRepresentation);
255 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
256 CustomRepresenter representer = new CustomRepresenter();
257 DumperOptions options = new DumperOptions();
258 options.setAllowReadOnlyProperties(false);
259 options.setPrettyFlow(true);
260 options.setDefaultFlowStyle(FlowStyle.FLOW);
261 options.setCanonical(false);
262 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
263 representer.setPropertyUtils(new UnsortedPropertyUtils());
264 Yaml yaml = new Yaml(representer, options);
265 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
266 StringBuilder sb = new StringBuilder();
267 sb.append(getConfiguration().getHeatEnvArtifactHeader());
268 sb.append(yamlAsString);
269 sb.append(getConfiguration().getHeatEnvArtifactFooter());
270 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
273 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
274 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
275 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
276 if (fillImports.isRight()) {
277 return Either.right(fillImports.right().value());
279 return Either.left(fillImports.left().value().left);
282 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
283 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
284 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
285 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
286 return Either.right(ToscaError.GENERAL_ERROR);
288 log.trace("start tosca export for {}", component.getUniqueId());
289 String toscaVersion = null;
290 if (component instanceof Resource) {
291 toscaVersion = ((Resource) component).getToscaVersion();
293 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
294 toscaTemplate.setMetadata(convertMetadata(component));
295 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
296 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
297 if (ModelConverter.isAtomicComponent(component)) {
298 log.trace("convert component as node type");
299 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
301 log.trace("convert component as topology template");
302 return convertToscaTemplate(component, toscaTemplate);
306 public List<Map<String, Map<String, String>>> getDefaultToscaImports(final String model) {
308 return getDefaultToscaImportConfig();
310 final List<ToscaImportByModel> importsByModel = toscaModelImportCassandraDao.findAllByModel(model);
311 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
312 for(ToscaImportByModel toscaImportByModel: importsByModel) {
313 final String fileName = FilenameUtils.getBaseName(toscaImportByModel.getFullPath());
314 importList.add(Map.of(fileName, Map.of("file", toscaImportByModel.getFullPath())));
319 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
320 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
321 if (importsRes.isRight()) {
322 return Either.right(importsRes.right().value());
324 toscaNode = importsRes.left().value().left;
325 Map<String, Component> componentCache = importsRes.left().value().right;
326 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
327 if (nodeTypesMapEither.isRight()) {
328 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
329 return Either.right(nodeTypesMapEither.right().value());
331 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
332 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
333 toscaNode.setNode_types(nodeTypesMap);
335 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
336 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
337 if (proxyInterfaceTypesEither.isRight()) {
338 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
339 return Either.right(proxyInterfaceTypesEither.right().value());
341 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
342 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
343 toscaNode.setInterface_types(proxyInterfaceTypes);
345 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
346 if (dataTypesEither.isRight()) {
347 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
348 return Either.right(ToscaError.GENERAL_ERROR);
350 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
351 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
352 List<InputDefinition> inputDef = component.getInputs();
353 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
354 if (!inputs.isEmpty()) {
355 topologyTemplate.setInputs(inputs);
357 final Map<String, ToscaProperty> outputs;
359 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
360 } catch (final ToscaConversionException e) {
361 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
362 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
363 return Either.right(ToscaError.GENERAL_ERROR);
365 if (!outputs.isEmpty()) {
366 topologyTemplate.setOutputs(outputs);
368 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
369 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
370 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
371 if (nodeTemplates.isRight()) {
372 return Either.right(nodeTemplates.right().value());
374 log.debug("node templates converted");
375 topologyTemplate.setNode_templates(nodeTemplates.left().value());
377 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
378 .createFrom(topologyTemplate.getNode_templates());
379 if (!relationshipTemplatesMap.isEmpty()) {
380 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
382 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
383 convertSubstitutionMappingFilter(component, substitutionMapping);
384 addGroupsToTopologyTemplate(component, topologyTemplate);
386 addPoliciesToTopologyTemplate(component, topologyTemplate);
387 } catch (SdcResourceNotFoundException e) {
388 log.debug("Fail to add policies to topology template:", e);
389 return Either.right(ToscaError.GENERAL_ERROR);
391 String toscaResourceName;
392 switch (component.getComponentType()) {
394 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
395 .getToscaResourceName();
398 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
401 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
402 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
404 substitutionMapping.setNode_type(toscaResourceName);
405 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
406 if (capabilities.isRight()) {
407 return Either.right(capabilities.right().value());
409 substitutionMapping = capabilities.left().value();
410 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
411 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
412 if (requirements.isRight()) {
413 return Either.right(requirements.right().value());
415 substitutionMapping = requirements.left().value();
416 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
417 if (!propertyMappingMap.isEmpty()) {
418 substitutionMapping.setProperties(propertyMappingMap);
420 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
421 if (!attributesMappingMap.isEmpty()) {
422 substitutionMapping.setAttributes(attributesMappingMap);
424 topologyTemplate.setSubstitution_mappings(substitutionMapping);
425 toscaNode.setTopology_template(topologyTemplate);
426 return Either.left(toscaNode);
429 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
430 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
431 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
435 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
436 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
437 if (groups != null) {
438 topologyTemplate.addGroups(groups);
442 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
443 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
444 if (policies != null) {
445 topologyTemplate.addPolicies(policies);
449 private Map<String, String> convertMetadata(Component component) {
450 return convertMetadata(component, false, null);
453 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
454 Map<String, String> toscaMetadata = new LinkedHashMap<>();
455 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
456 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
458 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
459 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
460 List<CategoryDefinition> categories = component.getCategories();
461 CategoryDefinition categoryDefinition = categories.get(0);
462 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
464 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
465 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
466 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
467 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
468 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
469 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
470 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
471 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
472 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
473 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
474 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
475 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
476 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
478 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
481 switch (component.getComponentType()) {
483 Resource resource = (Resource) component;
484 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
485 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
486 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
488 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
490 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
491 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
492 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
493 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
496 Service service = (Service) component;
497 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
498 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
499 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
500 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
501 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
502 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
503 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
506 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
507 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
508 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
512 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
514 for (final String key : component.getCategorySpecificMetadata().keySet()) {
515 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
516 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
519 return toscaMetadata;
522 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
523 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
524 return INVARIANT_UUID;
526 return jsonPresentationField.getPresentation();
529 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
530 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
531 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
532 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
533 return Either.right(ToscaError.GENERAL_ERROR);
535 Map<String, Component> componentCache = new HashMap<>();
536 if (!ModelConverter.isAtomicComponent(component)) {
537 final List<Map<String, Map<String, String>>> additionalImports =
538 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
539 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
540 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
541 if (isNotEmpty(toscaArtifacts)) {
542 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
543 if (artifactDefinition != null) {
544 Map<String, Map<String, String>> importsListMember = new HashMap<>();
545 Map<String, String> interfaceFiles = new HashMap<>();
546 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
547 StringBuilder keyNameBuilder = new StringBuilder();
548 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
549 .append("-interface");
550 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
551 additionalImports.add(importsListMember);
554 List<ComponentInstance> componentInstances = component.getComponentInstances();
555 if (componentInstances != null && !componentInstances.isEmpty()) {
556 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
558 toscaTemplate.setDependencies(dependencies);
559 toscaTemplate.setImports(additionalImports);
561 log.debug("currently imports supported for VF and service only");
563 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
566 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
567 return getConfiguration().getDefaultImports();
570 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
571 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
572 log.debug("createDependency componentCache {}", componentCache);
573 Component componentRI = componentCache.get(componentInstance.getComponentUid());
574 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
575 // all resource must be only once!
576 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
577 if ((resource.isRight()) && (log.isDebugEnabled())) {
578 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
579 componentInstance.getUniqueId());
582 final Component fetchedComponent = resource.left().value();
583 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
584 addDependencies(imports, dependencies, componentRI);
589 * Sets a componentCache from the given component/resource.
591 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
592 final Component fetchedComponent) {
593 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
594 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
595 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
596 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
597 .getToscaFullElement(componentInstance.getSourceModelUid());
598 if (sourceService.isRight() && (log.isDebugEnabled())) {
599 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
600 componentInstance.getUniqueId());
602 final Component fetchedSource = sourceService.left().value();
603 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
604 return fetchedSource;
606 return fetchedComponent;
610 * Retrieves all derived_from nodes and stores it in a predictable order.
612 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
613 final Component fetchedComponent) {
614 final Set<Component> componentsList = new LinkedHashSet<>();
615 if (fetchedComponent instanceof Resource) {
616 log.debug("fetchedComponent is a resource {}", fetchedComponent);
617 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
618 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
619 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
620 log.debug("Started entry.getValue() : {}", entry.getValue());
621 if (!NATIVE_ROOT.equals(entry.getValue())) {
622 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
623 if (resourcefetched != null && resourcefetched.isLeft()) {
624 componentsList.add(resourcefetched.left().value());
628 setImports(imports, dependencies, componentsList);
630 setImports(imports, dependencies, fetchedComponent);
636 * Returns all derived_from nodes found.
638 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
639 final Resource parentResource = (Resource) fetchedComponent;
640 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
641 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
642 componentsList.add(fetchedComponent);
643 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
644 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
645 .getToscaElement(componentInstance.getComponentUid());
646 if (resourcefetched != null && resourcefetched.isLeft()) {
647 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
648 if (MapUtils.isNotEmpty(derivedWithId)) {
649 derivedFromMapOfIdToName.putAll(derivedWithId);
654 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
656 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
657 return Optional.ofNullable(derivedFromMapOfIdToName);
661 * Creates a resource map and adds it to the import list.
663 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
664 final Set<Component> componentsList) {
665 componentsList.forEach(component -> setImports(imports, dependencies, component));
668 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
669 final Component component) {
670 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
671 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
672 if (artifactDefinition != null) {
673 final Map<String, String> files = new HashMap<>();
674 final String artifactName = artifactDefinition.getArtifactName();
675 files.put(IMPORTS_FILE_KEY, artifactName);
676 final StringBuilder keyNameBuilder = new StringBuilder();
677 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
678 keyNameBuilder.append("-");
679 keyNameBuilder.append(component.getName());
680 addImports(imports, keyNameBuilder, files);
681 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
682 if (!ModelConverter.isAtomicComponent(component)) {
683 final Map<String, String> interfaceFiles = new HashMap<>();
684 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
685 keyNameBuilder.append("-interface");
686 addImports(imports, keyNameBuilder, interfaceFiles);
692 * Adds the found resource to the import definition list.
694 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
695 final Map<String, String> files) {
696 final String mapKey = keyNameBuilder.toString();
697 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
698 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
699 importsListMember.put(keyNameBuilder.toString(), files);
700 imports.add(importsListMember);
704 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
705 Map<String, ToscaNodeType> nodeTypes) {
706 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
709 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
710 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
711 boolean isAssociatedComponent) {
712 log.debug("start convert node type for {}", component.getUniqueId());
713 ToscaNodeType toscaNodeType = createNodeType(component);
714 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
715 .getAllInterfaceLifecycleTypes(component.getModel());
716 if (lifecycleTypeEither.isRight()) {
717 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
718 return Either.right(ToscaError.GENERAL_ERROR);
720 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
721 .collect(Collectors.toList());
722 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
723 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
724 if (dataTypesEither.isRight()) {
725 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
726 return Either.right(ToscaError.GENERAL_ERROR);
728 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
729 List<InputDefinition> inputDef = component.getInputs();
730 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
731 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
732 addInputsToProperties(dataTypes, inputDef, mergedProperties);
733 final Map<String, ToscaAttribute> toscaAttributeMap;
734 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
735 if (!toscaAttributeMap.isEmpty()) {
736 toscaNodeType.setAttributes(toscaAttributeMap);
738 if (CollectionUtils.isNotEmpty(component.getProperties())) {
739 List<PropertyDefinition> properties = component.getProperties();
740 Map<String, ToscaProperty> convertedProperties = properties.stream()
741 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
742 .toMap(PropertyDataDefinition::getName,
743 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
744 // merge component properties and inputs properties
745 mergedProperties.putAll(convertedProperties);
747 if (MapUtils.isNotEmpty(mergedProperties)) {
748 toscaNodeType.setProperties(mergedProperties);
750 /* convert private data_types */
751 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
752 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
753 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
754 for (DataTypeDefinition dataType : privateDataTypes) {
755 log.debug("Emitting private data type: component.name={} dataType.name={}",
756 component.getNormalizedName(), dataType.getName());
757 ToscaDataType toscaDataType = new ToscaDataType();
758 toscaDataType.setDerived_from(dataType.getDerivedFromName());
759 toscaDataType.setDescription(dataType.getDescription());
760 toscaDataType.setVersion(dataType.getVersion());
761 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
762 toscaDataType.setProperties(dataType.getProperties().stream()
763 .collect(Collectors.toMap(
764 PropertyDataDefinition::getName,
765 s -> propertyConvertor
766 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
769 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
771 toscaNode.setData_types(toscaDataTypeMap);
774 // Extracted to method for code reuse
775 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
778 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
779 final Map<String, DataTypeDefinition> dataTypes) {
780 if (CollectionUtils.isEmpty(attributeList)) {
781 return Collections.emptyMap();
783 final AttributeConverter converter = new AttributeConverter(dataTypes);
784 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
785 for (final AttributeDefinition attributeDefinition : attributeList) {
786 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
788 return toscaAttributeMap;
791 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
792 Component component, ToscaTemplate toscaNode,
793 Map<String, ToscaNodeType> nodeTypes,
794 ToscaNodeType toscaNodeType,
795 Map<String, DataTypeDefinition> dataTypes) {
796 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
798 if (capabilities.isRight()) {
799 return Either.right(capabilities.right().value());
801 toscaNodeType = capabilities.left().value();
802 log.debug("Capabilities converted for {}", component.getUniqueId());
804 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
805 .convertRequirements(componentsCache, component, toscaNodeType);
806 if (requirements.isRight()) {
807 return Either.right(requirements.right().value());
809 toscaNodeType = requirements.left().value();
810 log.debug("Requirements converted for {}", component.getUniqueId());
812 String toscaResourceName;
813 switch (component.getComponentType()) {
815 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
816 .getMetadataDataDefinition()).getToscaResourceName();
819 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
820 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
823 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
824 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
827 nodeTypes.put(toscaResourceName, toscaNodeType);
828 toscaNode.setNode_types(nodeTypes);
829 log.debug("finish convert node type for {}", component.getUniqueId());
830 return Either.left(toscaNode);
833 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
834 final Map<String, Component> componentCache,
835 final Map<String, DataTypeDefinition> dataTypes,
836 final ToscaTopolgyTemplate topologyTemplate) {
838 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
839 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
840 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
841 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
842 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
844 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
845 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
846 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
848 Map<String, ToscaGroupTemplate> groupsMap = null;
849 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
850 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
851 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
852 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
854 nodeTemplate.setType(componentInstance.getToscaComponentName());
855 nodeTemplate.setDirectives(componentInstance.getDirectives());
856 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
858 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
859 .getOriginComponent(componentCache, componentInstance);
860 if (originComponentRes.isRight()) {
861 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
864 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
865 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
866 if (requirements.isRight()) {
867 convertNodeTemplatesRes = Either.right(requirements.right().value());
870 final String instanceUniqueId = componentInstance.getUniqueId();
871 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
873 nodeTemplate = requirements.left().value();
875 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
877 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
878 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
879 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
881 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
884 final Either<ToscaNodeTemplate, ToscaError> capabilities =
885 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
886 if (capabilities.isRight()) {
887 convertNodeTemplatesRes = Either.right(capabilities.right().value());
890 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
892 nodeTemplate = capabilities.left().value();
893 final Map<String, Object> props = new HashMap<>();
894 final Map<String, Object> attribs = new HashMap<>();
896 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
897 // Adds the properties of parent component to map
898 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
899 addAttributesOfParentComponent(originalComponent, attribs);
902 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
903 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
905 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
906 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
909 if (componentInstancesInputs != null
910 && componentInstancesInputs.containsKey(instanceUniqueId)
911 && !isComponentOfTypeServiceProxy(componentInstance)) {
912 //For service proxy the inputs are already handled under instance properties above
913 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
916 //M3[00001] - NODE TEMPLATE INTERFACES - START
917 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
918 //M3[00001] - NODE TEMPLATE INTERFACES - END
919 if (MapUtils.isNotEmpty(props)) {
920 nodeTemplate.setProperties(props);
922 if (MapUtils.isNotEmpty(attribs)) {
923 nodeTemplate.setAttributes(attribs);
926 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
927 if (CollectionUtils.isNotEmpty(groupInstances)) {
928 if (groupsMap == null) {
929 groupsMap = new HashMap<>();
931 for (final GroupInstance groupInst : groupInstances) {
932 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
933 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
938 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
940 if (groupsMap != null) {
941 log.debug("instance groups added");
942 topologyTemplate.addGroups(groupsMap);
944 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
945 ((Service) component).getForwardingPaths())) {
946 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
947 ForwardingPathToscaUtil
948 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
949 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
951 if (convertNodeTemplatesRes == null) {
952 convertNodeTemplatesRes = Either.left(nodeTemplates);
954 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
955 return convertNodeTemplatesRes;
958 private void handleInstanceInterfaces(
959 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
960 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
961 String instanceUniqueId,
962 Component parentComponent) {
964 if (MapUtils.isEmpty(componentInstanceInterfaces)
965 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
966 nodeTemplate.setInterfaces(null);
970 final List<ComponentInstanceInterface> currServiceInterfaces =
971 componentInstanceInterfaces.get(instanceUniqueId);
973 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
974 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
975 .getUniqueId(), instInterface));
977 final Map<String, Object> interfaceMap = interfacesOperationsConverter
978 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
979 isComponentOfTypeServiceProxy(componentInstance));
981 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
982 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
985 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
986 return Objects.nonNull(componentInstance.getOriginType())
987 && componentInstance.getOriginType().getValue().equals("Service Proxy");
990 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
991 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
992 String instanceUniqueId, Map<String, Object> props) {
994 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
995 if (instanceInputsList != null) {
996 instanceInputsList.forEach(input -> {
997 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
998 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1003 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1004 final Map<String, DataTypeDefinition> dataTypes,
1005 final String instanceUniqueId,
1006 final Map<String, Object> props) {
1008 if (isNotEmpty(componentInstancesProperties)) {
1009 componentInstancesProperties.get(instanceUniqueId)
1010 // Converts and adds each value to property map
1011 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1015 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1016 final String instanceUniqueId,
1017 final Map<String, Object> attribs) {
1019 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1020 componentInstancesAttributes.get(instanceUniqueId).stream()
1021 // Filters out Attributes with empty default values
1022 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1023 // Converts and adds each value to attribute map
1024 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1028 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1029 Component componentOfInstance, Map<String, Object> props) {
1031 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1032 if (isNotEmpty(componentProperties)) {
1033 componentProperties.stream()
1034 // Filters out properties with empty default values
1035 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1036 // Converts and adds each value to property map
1037 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1041 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1043 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1044 if (isNotEmpty(componentAttributes)) {
1045 componentAttributes.stream()
1046 // Filters out Attributes with empty default values
1047 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1048 // Converts and adds each value to attribute map
1049 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1053 private ToscaNodeType createNodeType(Component component) {
1054 ToscaNodeType toscaNodeType = new ToscaNodeType();
1055 if (ModelConverter.isAtomicComponent(component)) {
1056 if (((Resource) component).getDerivedFrom() != null) {
1057 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1059 toscaNodeType.setDescription(component.getDescription());
1061 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1063 toscaNodeType.setDerived_from(derivedFrom);
1065 return toscaNodeType;
1068 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1070 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1071 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1072 List<ComponentInstance> componentInstances = container.getComponentInstances();
1073 if (CollectionUtils.isEmpty(componentInstances)) {
1076 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1077 componentInstances.stream()
1078 .filter(this::isComponentOfTypeServiceProxy)
1079 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1080 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1083 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1084 Component serviceComponent;
1085 ComponentParametersView componentParametersView = new ComponentParametersView();
1086 componentParametersView.disableAll();
1087 componentParametersView.setIgnoreInterfaces(false);
1088 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1089 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1090 if (service.isRight()) {
1091 log.debug("Failed to fetch original service component with id {} for instance {}",
1092 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1093 return Either.right(ToscaError.GENERAL_ERROR);
1095 serviceComponent = service.left().value();
1098 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1099 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1100 if (lifecycleTypeEither.isRight()) {
1101 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1102 return Either.right(ToscaError.GENERAL_ERROR);
1105 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1106 .map(InterfaceDataDefinition::getType)
1107 .collect(Collectors.toList());
1108 //Add interface types for local interfaces in the original service component for proxy
1109 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1110 allGlobalInterfaceTypes);
1111 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1112 proxyInterfaceTypes.putAll(localInterfaceTypes);
1116 return Either.left(proxyInterfaceTypes);
1119 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1120 Component container) {
1122 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1123 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1125 List<ComponentInstance> componentInstances = container.getComponentInstances();
1127 if (componentInstances == null || componentInstances.isEmpty()) {
1130 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1131 List<ComponentInstance> proxyInst = componentInstances.stream()
1132 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1133 .collect(Collectors.toList());
1134 if (proxyInst != null && !proxyInst.isEmpty()) {
1135 for (ComponentInstance inst : proxyInst) {
1136 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1140 if (serviceProxyInstanceList.isEmpty()) {
1143 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1144 .getLatestByName("serviceProxy", null);
1145 if (serviceProxyOrigin.isRight()) {
1146 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1147 serviceProxyOrigin.right().value());
1148 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1150 Component origComponent = serviceProxyOrigin.left().value();
1152 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1153 Component serviceComponent = null;
1154 ComponentParametersView componentParametersView = new ComponentParametersView();
1155 componentParametersView.disableAll();
1156 componentParametersView.setIgnoreCategories(false);
1157 componentParametersView.setIgnoreProperties(false);
1158 componentParametersView.setIgnoreInputs(false);
1159 componentParametersView.setIgnoreInterfaces(false);
1160 componentParametersView.setIgnoreRequirements(false);
1161 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1162 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1163 if (service.isRight()) {
1164 log.debug("Failed to fetch resource with id {} for instance {}",
1165 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1167 serviceComponent = service.left().value();
1170 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1171 entryProxy.getValue());
1172 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1175 return Either.left(nodeTypesMap);
1178 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1179 final Component container, final ToscaTemplate toscaNode) {
1180 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1182 if (CollectionUtils.isEmpty(componentInstances)) {
1185 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1186 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1187 .collect(Collectors.toList());
1188 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1189 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1190 final Map<String, ToscaNodeType> nodeTypes =
1191 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1192 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1198 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1199 Component proxyComponent, ComponentInstance componentInstance) {
1200 ToscaNodeType toscaNodeType = new ToscaNodeType();
1201 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1203 toscaNodeType.setDerived_from(derivedFrom);
1204 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel());
1205 if (dataTypesEither.isRight()) {
1206 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1208 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1209 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1210 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1212 if (MapUtils.isNotEmpty(capabilities)) {
1213 toscaNodeType.setCapabilities(capabilities);
1215 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1216 .convertProxyRequirements(componentCache, componentInstance);
1217 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1218 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1220 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1221 proxyProperties.ifPresent(toscaNodeType::setProperties);
1223 Map<String, Object> interfaceMap = new HashMap<>();
1224 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1225 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1226 if (proxyInterfaces.isPresent()) {
1227 interfaceMap = proxyInterfaces.get();
1230 interfaceMap = interfacesOperationsConverter
1231 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1234 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1235 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1237 return toscaNodeType;
1240 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1241 ComponentInstance componentInstance,
1242 List<RequirementCapabilityRelDef> relations,
1243 ToscaNodeTemplate nodeTypeTemplate,
1244 Component originComponent,
1245 Map<String, Component> componentCache) {
1247 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1249 if (isNotEmpty(requirementDefinitionList)) {
1251 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1252 if (!toscaRequirements.isEmpty()) {
1253 nodeTypeTemplate.setRequirements(toscaRequirements);
1255 } catch (final Exception e) {
1256 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1257 componentInstance.getName(), e);
1258 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1261 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1262 return Either.left(nodeTypeTemplate);
1265 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1266 final ComponentInstance componentInstance,
1267 final List<RequirementCapabilityRelDef> filteredRelations,
1268 final Component originComponent,
1269 final Map<String, Component> componentCache)
1270 throws ToscaExportException {
1272 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1273 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1274 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1275 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1276 toscaRequirements.add(toscaTemplateRequirementMap);
1279 return toscaRequirements;
1282 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1283 List<RequirementCapabilityRelDef> relations) {
1284 return relations.stream()
1285 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1288 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1289 final Component fromOriginComponent,
1290 final List<ComponentInstance> instancesList,
1291 final RequirementCapabilityRelDef relationshipDefinition,
1292 final Map<String, Component> componentCache)
1293 throws ToscaExportException {
1295 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1296 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1297 .getRelationships().get(0);
1298 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1300 final ComponentInstance toInstance = instancesList.stream()
1301 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1302 .findFirst().orElse(null);
1303 if (toInstance == null) {
1304 final String errorMsg = String
1305 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1306 relationshipDefinition.getToNode());
1307 log.debug(errorMsg);
1308 throw new ToscaExportException(errorMsg);
1310 final Optional<RequirementDefinition> reqOpt =
1311 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1312 if (reqOpt.isEmpty()) {
1313 final String errorMsg = String
1314 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1315 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1316 log.debug(errorMsg);
1317 throw new ToscaExportException(errorMsg);
1319 final ComponentParametersView filter = new ComponentParametersView(true);
1320 filter.setIgnoreComponentInstances(false);
1321 filter.setIgnoreCapabilities(false);
1322 filter.setIgnoreGroups(false);
1323 final Either<Component, StorageOperationStatus> getOriginRes =
1324 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1325 if (getOriginRes.isRight()) {
1326 final String errorMsg = String.format(
1327 "Failed to build substituted name for the requirement %s. "
1328 + "Failed to get an origin component with uniqueId %s",
1329 reqOpt.get().getName(), toInstance.getActualComponentUid());
1330 log.debug(errorMsg);
1331 throw new ToscaExportException(errorMsg);
1333 final Component toOriginComponent = getOriginRes.left().value();
1334 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1335 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1336 if (capOpt.isEmpty()) {
1337 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1338 if (capOpt.isEmpty()) {
1339 final String errorMsg = String
1340 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1341 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1342 log.debug(errorMsg);
1343 throw new ToscaExportException(errorMsg);
1346 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1347 capabilityRequirementRelationship, toInstance, componentCache);
1350 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1351 CapabilityDefinition capability) {
1352 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1353 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1356 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1357 Component toOriginComponent, Component fromOriginComponent,
1358 RequirementDefinition requirement) {
1359 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1360 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1361 if (!cap.isPresent()) {
1362 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1363 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1368 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1369 final Component toOriginComponent,
1370 final CapabilityDefinition capability,
1371 final RequirementDefinition requirement,
1372 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1373 final ComponentInstance toInstance,
1374 final Map<String, Component> componentCache)
1375 throws ToscaExportException {
1377 List<String> reducedPath = capability.getPath();
1378 if (capability.getOwnerId() != null) {
1379 reducedPath = capabilityRequirementConverter
1380 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1382 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1383 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1384 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1385 if (capabilityNameEither.isRight()) {
1386 final String errorMsg = String.format(
1387 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1388 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1391 throw new ToscaExportException(errorMsg);
1393 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1394 .buildSubstitutedName(componentCache, fromOriginComponent,
1395 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1396 if (requirementNameEither.isRight()) {
1397 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1398 + "with name %s on a component with uniqueId %s",
1399 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1400 log.debug(errorMsg);
1401 throw new ToscaExportException(errorMsg);
1403 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1404 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1405 toscaRequirement.setNode(toInstance.getName());
1406 toscaRequirement.setCapability(capabilityNameEither.left().value());
1407 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1408 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1410 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1414 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1415 Map<String, List<RequirementDefinition>> reqMap,
1416 RelationshipInfo reqAndRelationshipPair,
1417 String fromInstanceId) {
1418 for (List<RequirementDefinition> reqList : reqMap.values()) {
1419 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1420 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1422 if (reqOpt.isPresent()) {
1426 return Optional.empty();
1430 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1431 * 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
1432 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1434 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1435 RequirementDefinition requirement, String fromInstanceId) {
1436 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1437 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1438 reqAndRelationshipPair.getRequirement());
1441 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1445 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1446 Component originComponent) {
1447 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1448 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1449 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1452 private boolean isCvfc(Component component) {
1453 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1456 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1457 Map<String, Component> componentCache) {
1458 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1459 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1460 .convertSubstitutionMappingCapabilities(componentCache, component);
1461 if (toscaCapabilitiesRes.isRight()) {
1462 result = Either.right(toscaCapabilitiesRes.right().value());
1463 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1464 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1465 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1466 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1468 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1472 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1473 Map<String, DataTypeDefinition> dataTypes) {
1474 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1475 if (!toscaCapabilities.isEmpty()) {
1476 nodeType.setCapabilities(toscaCapabilities);
1478 log.debug("Finish convert Capabilities for node type");
1479 return Either.left(nodeType);
1482 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1483 if (artifacts == null) {
1486 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1487 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1488 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1489 artifact.setFile(entry.getValue().getFile());
1490 artifact.setType(entry.getValue().getType());
1491 arts.put(entry.getKey(), artifact);
1496 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1497 if (inNodeFilter == null) {
1500 NodeFilter nodeFilter = new NodeFilter();
1501 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1502 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1503 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1504 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1505 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1506 copyNodeFilterProperties(origProperties, propertiesCopy);
1507 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1508 nodeFilter.setCapabilities(capabilitiesCopy);
1510 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1511 nodeFilter.setProperties(propertiesCopy);
1513 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1514 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1518 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1519 if (substitutionFilterDataDefinition == null) {
1522 NodeFilter nodeFilter = new NodeFilter();
1523 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1524 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1525 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1526 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1527 nodeFilter.setProperties(propertiesCopy);
1529 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1530 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1533 private Object cloneToscaId(Object toscaId) {
1534 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1537 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1538 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1539 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1542 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1543 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1544 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1548 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1549 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1550 CapabilityFilter capabilityFilter = new CapabilityFilter();
1551 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1552 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1553 capabilityFilter.setProperties(propertiesCopy);
1554 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1555 capabilitiesCopy.add(capabilityFilterCopyMap);
1559 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1560 List<Map<String, List<Object>>> propertiesCopy) {
1561 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1564 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1565 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1566 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1567 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1568 String propertyName = propertyDataDefinition.getName();
1569 if (propertyMapCopy.containsKey(propertyName)) {
1570 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1572 if (propertyName != null) {
1573 List<Object> propsList = new ArrayList<>();
1574 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1575 propertyMapCopy.put(propertyName, propsList);
1577 propertyMapCopy.putAll(propertyValObj);
1582 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1585 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1586 final List<Map<String, List<Object>>> propertiesCopy) {
1587 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1590 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1591 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1592 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1593 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1594 final String propertyName = propertyDataDefinition.getName();
1595 if (propertyMapCopy.containsKey(propertyName)) {
1596 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1598 if (propertyName != null) {
1599 final List<Object> propsList = new ArrayList<>();
1600 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1601 propertyMapCopy.put(propertyName, propsList);
1603 propertyMapCopy.putAll(propertyValObj);
1608 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1611 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1612 if (propertyValObj.containsKey(propertyName)) {
1613 propsList.add(propertyValObj.get(propertyName));
1615 propsList.add(propertyValObj);
1619 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1620 Map<String, List<Object>> tempMap = new HashMap<>();
1621 tempMap.put(entry.getKey(), entry.getValue());
1622 propertiesCopy.add(tempMap);
1625 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1626 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1627 return Collections.emptyMap();
1629 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1630 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1633 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1634 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1635 return Collections.emptyMap();
1637 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1638 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1641 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1642 if (Objects.isNull(proxyComponent)) {
1643 return Optional.empty();
1645 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1646 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1647 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1648 proxyProperties.putAll(proxyComponent.getProperties().stream()
1649 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1650 .toMap(PropertyDataDefinition::getName,
1651 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1653 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1656 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1657 Map<String, ToscaProperty> mergedProperties) {
1658 if (CollectionUtils.isEmpty(componentInputs)) {
1661 for (InputDefinition input : componentInputs) {
1662 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1663 mergedProperties.put(input.getName(), property);
1667 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1668 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1669 return Optional.empty();
1671 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1672 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1674 // always available in the proxy node template
1675 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1677 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1680 private static class CustomRepresenter extends Representer {
1682 CustomRepresenter() {
1684 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1685 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1686 // null representer is exceptional and it is stored as an instance
1689 this.nullRepresenter = new RepresentNull();
1692 public boolean validateGetInputValue(final Object valueObj) {
1693 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1696 if (valueObj instanceof List) {
1697 return ((List) valueObj).size() > 1;
1702 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1703 if (valueObj instanceof List) {
1704 return ((List) valueObj).size() > 1;
1710 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1711 if (propertyValue == null) {
1714 // skip not relevant for Tosca property
1715 if ("dependencies".equals(property.getName())) {
1718 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1721 removeDefaultP(propertyValue);
1722 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1723 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1724 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1726 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1729 private void removeDefaultP(final Object propertyValue) {
1730 if (propertyValue instanceof Map) {
1731 final Map mapPropertyValue = ((Map) propertyValue);
1732 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1733 Object defaultValue = null;
1734 while (iter.hasNext()) {
1735 final Map.Entry entry = iter.next();
1736 if ("_defaultp_".equals(entry.getKey())) {
1737 defaultValue = entry.getValue();
1739 } else if (entry.getValue() instanceof Map) {
1740 removeDefaultP(entry.getValue());
1743 if (defaultValue != null) {
1744 mapPropertyValue.putIfAbsent("default", defaultValue);
1750 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1751 // remove the bean type from the output yaml (!! ...)
1752 if (!classTags.containsKey(javaBean.getClass())) {
1753 addClassTag(javaBean.getClass(), Tag.MAP);
1755 return super.representJavaBean(properties, javaBean);
1758 private class RepresentToscaAttribute implements Represent {
1761 public Node representData(Object data) {
1762 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1763 return represent(toscaAttribute.asToscaMap());
1767 private class RepresentToscaPropertyAssignment implements Represent {
1769 public Node representData(Object data) {
1770 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1771 if (toscaOperationAssignment.getValue() instanceof String) {
1772 final String stringValue = (String) toscaOperationAssignment.getValue();
1773 if (isPropertyOrAttributeFunction(stringValue)) {
1774 return representGetAttribute(stringValue);
1776 return representScalar(Tag.STR, stringValue);
1778 return represent(null);
1781 public Node representGetAttribute(final String getAttributeFunction) {
1782 return represent(new Yaml().load(getAttributeFunction));
1785 public boolean isPropertyOrAttributeFunction(final String value) {
1787 final Yaml yaml = new Yaml();
1788 final Object yamlObj = yaml.load(value);
1789 if (!(yamlObj instanceof Map)) {
1792 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1793 if (getAttributeMap.size() != 1) {
1796 final List<String> functionList = Arrays
1797 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1798 final Optional<String> function = getAttributeMap.keySet().stream()
1799 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1800 if (function.isEmpty()) {
1803 final String functionName = function.get();
1804 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1805 if (GET_INPUT.getFunctionName().equals(functionName)) {
1806 return validateGetInputValue(getAttributeValueObj);
1808 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1810 } catch (final Exception ignored) {
1816 private class RepresentNull implements Represent {
1819 public Node representData(Object data) {
1820 // possible values are here http://yaml.org/type/null.html
1821 return representScalar(Tag.NULL, "");
1826 private static class UnsortedPropertyUtils extends PropertyUtils {
1829 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1830 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1831 return new LinkedHashSet<>(fields);
1835 private Configuration getConfiguration() {
1836 return ConfigurationManager.getConfigurationManager().getConfiguration();