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.lang.StringUtils;
51 import org.apache.commons.lang3.tuple.ImmutablePair;
52 import org.apache.commons.lang3.tuple.ImmutableTriple;
53 import org.apache.commons.lang3.tuple.Triple;
54 import org.onap.sdc.tosca.services.YamlUtil;
55 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
56 import org.openecomp.sdc.be.config.ConfigurationManager;
57 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
58 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
59 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
60 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
69 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
70 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
71 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
73 import org.openecomp.sdc.be.exception.ToscaExportException;
74 import org.openecomp.sdc.be.model.ArtifactDefinition;
75 import org.openecomp.sdc.be.model.AttributeDefinition;
76 import org.openecomp.sdc.be.model.CapabilityDefinition;
77 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
78 import org.openecomp.sdc.be.model.Component;
79 import org.openecomp.sdc.be.model.ComponentInstance;
80 import org.openecomp.sdc.be.model.ComponentInstanceInput;
81 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
82 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
83 import org.openecomp.sdc.be.model.ComponentParametersView;
84 import org.openecomp.sdc.be.model.DataTypeDefinition;
85 import org.openecomp.sdc.be.model.GroupInstance;
86 import org.openecomp.sdc.be.model.InputDefinition;
87 import org.openecomp.sdc.be.model.InterfaceDefinition;
88 import org.openecomp.sdc.be.model.PropertyDefinition;
89 import org.openecomp.sdc.be.model.RelationshipInfo;
90 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
91 import org.openecomp.sdc.be.model.RequirementDefinition;
92 import org.openecomp.sdc.be.model.Resource;
93 import org.openecomp.sdc.be.model.Service;
94 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
95 import org.openecomp.sdc.be.model.category.CategoryDefinition;
96 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
97 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
98 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
99 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
100 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
101 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
102 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
103 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
104 import org.openecomp.sdc.be.tosca.model.NodeFilter;
105 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
106 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
107 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
108 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
109 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
110 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
111 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
112 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
113 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
114 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
115 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
116 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
117 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
118 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
119 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
120 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
121 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
122 import org.openecomp.sdc.be.tosca.utils.InputConverter;
123 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
124 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
125 import org.openecomp.sdc.common.log.wrappers.Logger;
126 import org.springframework.beans.factory.annotation.Autowired;
127 import org.yaml.snakeyaml.DumperOptions;
128 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
129 import org.yaml.snakeyaml.Yaml;
130 import org.yaml.snakeyaml.introspector.BeanAccess;
131 import org.yaml.snakeyaml.introspector.Property;
132 import org.yaml.snakeyaml.introspector.PropertyUtils;
133 import org.yaml.snakeyaml.nodes.MappingNode;
134 import org.yaml.snakeyaml.nodes.Node;
135 import org.yaml.snakeyaml.nodes.NodeTuple;
136 import org.yaml.snakeyaml.nodes.Tag;
137 import org.yaml.snakeyaml.representer.Represent;
138 import org.yaml.snakeyaml.representer.Representer;
141 @org.springframework.stereotype.Component("tosca-export-handler")
142 public class ToscaExportHandler {
144 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
145 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
146 private static final String INVARIANT_UUID = "invariantUUID";
147 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
148 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
149 private static final String IMPORTS_FILE_KEY = "file";
150 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
151 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
152 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
153 private static final String NATIVE_ROOT = "tosca.nodes.Root";
154 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List.of("Service Function", "Service Role", "Naming Policy", "Service Type");
155 private static final YamlUtil yamlUtil = new YamlUtil();
156 private ApplicationDataTypeCache dataTypeCache;
157 private ToscaOperationFacade toscaOperationFacade;
158 private CapabilityRequirementConverter capabilityRequirementConverter;
159 private PolicyExportParser policyExportParser;
160 private GroupExportParser groupExportParser;
161 private PropertyConvertor propertyConvertor;
162 private InputConverter inputConverter;
163 private OutputConverter outputConverter;
164 private InterfaceLifecycleOperation interfaceLifecycleOperation;
165 private InterfacesOperationsConverter interfacesOperationsConverter;
168 public ToscaExportHandler(final ApplicationDataTypeCache dataTypeCache, final ToscaOperationFacade toscaOperationFacade,
169 final CapabilityRequirementConverter capabilityRequirementConverter, final PolicyExportParser policyExportParser,
170 final GroupExportParser groupExportParser, final PropertyConvertor propertyConvertor,
171 final InputConverter inputConverter, final OutputConverter outputConverter,
172 final InterfaceLifecycleOperation interfaceLifecycleOperation,
173 final InterfacesOperationsConverter interfacesOperationsConverter) {
174 this.dataTypeCache = dataTypeCache;
175 this.toscaOperationFacade = toscaOperationFacade;
176 this.capabilityRequirementConverter = capabilityRequirementConverter;
177 this.policyExportParser = policyExportParser;
178 this.groupExportParser = groupExportParser;
179 this.propertyConvertor = propertyConvertor;
180 this.inputConverter = inputConverter;
181 this.outputConverter = outputConverter;
182 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
183 this.interfacesOperationsConverter = interfacesOperationsConverter;
186 public static String getInterfaceFilename(String artifactName) {
187 return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME;
190 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
191 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
194 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
195 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
198 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
199 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
202 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
203 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImportConfig());
204 if (CollectionUtils.isEmpty(imports)) {
205 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
206 return Either.right(ToscaError.GENERAL_ERROR);
208 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
209 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType().startsWith("org.openecomp.resource.abstract.nodes.")) {
210 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade.getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion());
211 if (baseType.isLeft() && baseType.left().value() != null) {
212 addDependencies(imports, dependencies , baseType.left().value());
214 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
218 String toscaVersion = null;
219 if (component instanceof Resource) {
220 toscaVersion = ((Resource) component).getToscaVersion();
222 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
223 toscaTemplate.setImports(imports);
224 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
225 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
226 isAssociatedComponent);
227 if (toscaTemplateRes.isRight()) {
228 return Either.right(toscaTemplateRes.right().value());
230 toscaTemplate = toscaTemplateRes.left().value();
231 toscaTemplate.setDependencies(dependencies);
232 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
233 return Either.left(toscaRepresentation);
236 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
237 CustomRepresenter representer = new CustomRepresenter();
238 DumperOptions options = new DumperOptions();
239 options.setAllowReadOnlyProperties(false);
240 options.setPrettyFlow(true);
241 options.setDefaultFlowStyle(FlowStyle.FLOW);
242 options.setCanonical(false);
243 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
244 representer.setPropertyUtils(new UnsortedPropertyUtils());
245 Yaml yaml = new Yaml(representer, options);
246 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
247 StringBuilder sb = new StringBuilder();
248 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
249 sb.append(yamlAsString);
250 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
251 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
254 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
255 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
256 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
257 if (fillImports.isRight()) {
258 return Either.right(fillImports.right().value());
260 return Either.left(fillImports.left().value().left);
263 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
264 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
265 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
266 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
267 return Either.right(ToscaError.GENERAL_ERROR);
269 log.trace("start tosca export for {}", component.getUniqueId());
270 String toscaVersion = null;
271 if (component instanceof Resource) {
272 toscaVersion = ((Resource) component).getToscaVersion();
274 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
275 toscaTemplate.setMetadata(convertMetadata(component));
276 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
277 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
278 if (ModelConverter.isAtomicComponent(component)) {
279 log.trace("convert component as node type");
280 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
282 log.trace("convert component as topology template");
283 return convertToscaTemplate(component, toscaTemplate);
287 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
288 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
289 if (importsRes.isRight()) {
290 return Either.right(importsRes.right().value());
292 toscaNode = importsRes.left().value().left;
293 Map<String, Component> componentCache = importsRes.left().value().right;
294 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
295 if (nodeTypesMapEither.isRight()) {
296 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
297 return Either.right(nodeTypesMapEither.right().value());
299 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
300 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
301 toscaNode.setNode_types(nodeTypesMap);
303 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
304 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
305 if (proxyInterfaceTypesEither.isRight()) {
306 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
307 return Either.right(proxyInterfaceTypesEither.right().value());
309 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
310 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
311 toscaNode.setInterface_types(proxyInterfaceTypes);
313 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
314 if (dataTypesEither.isRight()) {
315 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
316 return Either.right(ToscaError.GENERAL_ERROR);
318 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
319 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
320 List<InputDefinition> inputDef = component.getInputs();
321 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
322 if (!inputs.isEmpty()) {
323 topologyTemplate.setInputs(inputs);
325 final Map<String, ToscaProperty> outputs;
327 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
328 } catch (final ToscaConversionException e) {
329 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
330 "Could not parse component '{}' outputs. Component unique id '{}'.", new Object[]{component.getName(), component.getUniqueId(), e});
331 return Either.right(ToscaError.GENERAL_ERROR);
333 if (!outputs.isEmpty()) {
334 topologyTemplate.setOutputs(outputs);
336 final List<ComponentInstance> componentInstances = component.getComponentInstances();
337 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
338 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
339 if (CollectionUtils.isNotEmpty(componentInstances)) {
340 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = convertNodeTemplates(component, componentInstances,
341 componentInstancesProperties, componentInstanceInterfaces, componentCache, dataTypes, topologyTemplate);
342 if (nodeTemplates.isRight()) {
343 return Either.right(nodeTemplates.right().value());
345 log.debug("node templates converted");
346 topologyTemplate.setNode_templates(nodeTemplates.left().value());
348 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
349 .createFrom(topologyTemplate.getNode_templates());
350 if (!relationshipTemplatesMap.isEmpty()) {
351 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
353 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
354 convertSubstitutionMappingFilter(component, substitutionMapping);
355 addGroupsToTopologyTemplate(component, topologyTemplate);
357 addPoliciesToTopologyTemplate(component, topologyTemplate);
358 } catch (SdcResourceNotFoundException e) {
359 log.debug("Fail to add policies to topology template:", e);
360 return Either.right(ToscaError.GENERAL_ERROR);
362 String toscaResourceName;
363 switch (component.getComponentType()) {
365 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
366 .getToscaResourceName();
369 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
372 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
373 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
375 substitutionMapping.setNode_type(toscaResourceName);
376 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
377 if (capabilities.isRight()) {
378 return Either.right(capabilities.right().value());
380 substitutionMapping = capabilities.left().value();
381 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
382 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
383 if (requirements.isRight()) {
384 return Either.right(requirements.right().value());
386 substitutionMapping = requirements.left().value();
387 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
388 if (!propertyMappingMap.isEmpty()) {
389 substitutionMapping.setProperties(propertyMappingMap);
391 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
392 if (!attributesMappingMap.isEmpty()) {
393 substitutionMapping.setAttributes(attributesMappingMap);
395 topologyTemplate.setSubstitution_mappings(substitutionMapping);
396 toscaNode.setTopology_template(topologyTemplate);
397 return Either.left(toscaNode);
400 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
401 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
402 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
406 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
407 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
408 if (groups != null) {
409 topologyTemplate.addGroups(groups);
413 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
414 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
415 if (policies != null) {
416 topologyTemplate.addPolicies(policies);
420 private Map<String, String> convertMetadata(Component component) {
421 return convertMetadata(component, false, null);
424 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
425 Map<String, String> toscaMetadata = new LinkedHashMap<>();
426 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
427 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
429 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
430 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
431 List<CategoryDefinition> categories = component.getCategories();
432 CategoryDefinition categoryDefinition = categories.get(0);
433 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
435 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
436 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
437 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
438 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
439 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
440 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
441 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
442 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
443 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
444 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
445 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
446 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
447 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
449 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
452 switch (component.getComponentType()) {
454 Resource resource = (Resource) component;
455 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
456 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
457 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
459 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
461 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
462 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
463 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
464 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
467 Service service = (Service) component;
468 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
469 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
470 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
471 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
472 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
473 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
474 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
477 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
478 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
479 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
483 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
485 for (final String key : component.getCategorySpecificMetadata().keySet()) {
486 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key))
487 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
489 return toscaMetadata;
492 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
493 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
494 return INVARIANT_UUID;
496 return jsonPresentationField.getPresentation();
499 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
500 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
501 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
502 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
503 return Either.right(ToscaError.GENERAL_ERROR);
505 Map<String, Component> componentCache = new HashMap<>();
506 if (!ModelConverter.isAtomicComponent(component)) {
507 final List<Map<String, Map<String, String>>> additionalImports =
508 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
509 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
510 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
511 if (isNotEmpty(toscaArtifacts)) {
512 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
513 if (artifactDefinition != null) {
514 Map<String, Map<String, String>> importsListMember = new HashMap<>();
515 Map<String, String> interfaceFiles = new HashMap<>();
516 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
517 StringBuilder keyNameBuilder = new StringBuilder();
518 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
519 .append("-interface");
520 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
521 additionalImports.add(importsListMember);
524 List<ComponentInstance> componentInstances = component.getComponentInstances();
525 if (componentInstances != null && !componentInstances.isEmpty()) {
526 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
528 toscaTemplate.setDependencies(dependencies);
529 toscaTemplate.setImports(additionalImports);
531 log.debug("currently imports supported for VF and service only");
533 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
536 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
537 return ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports();
540 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
541 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
542 log.debug("createDependency componentCache {}", componentCache);
543 Component componentRI = componentCache.get(componentInstance.getComponentUid());
544 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
545 // all resource must be only once!
546 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
547 if ((resource.isRight()) && (log.isDebugEnabled())) {
548 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
549 componentInstance.getUniqueId());
552 final Component fetchedComponent = resource.left().value();
553 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
554 addDependencies(imports, dependencies, componentRI);
559 * Sets a componentCache from the given component/resource.
561 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
562 final Component fetchedComponent) {
563 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
564 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
565 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
566 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
567 .getToscaFullElement(componentInstance.getSourceModelUid());
568 if (sourceService.isRight() && (log.isDebugEnabled())) {
569 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
570 componentInstance.getUniqueId());
572 final Component fetchedSource = sourceService.left().value();
573 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
574 return fetchedSource;
576 return fetchedComponent;
580 * Retrieves all derived_from nodes and stores it in a predictable order.
582 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
583 final Component fetchedComponent) {
584 final Set<Component> componentsList = new LinkedHashSet<>();
585 if (fetchedComponent instanceof Resource) {
586 log.debug("fetchedComponent is a resource {}", fetchedComponent);
587 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
588 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
589 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
590 log.debug("Started entry.getValue() : {}", entry.getValue());
591 if (!NATIVE_ROOT.equals(entry.getValue())) {
592 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
593 if (resourcefetched != null && resourcefetched.isLeft()) {
594 componentsList.add(resourcefetched.left().value());
598 setImports(imports, dependencies, componentsList);
600 setImports(imports, dependencies, fetchedComponent);
606 * Returns all derived_from nodes found.
608 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
609 final Resource parentResource = (Resource) fetchedComponent;
610 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
611 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
612 componentsList.add(fetchedComponent);
613 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
614 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
615 .getToscaElement(componentInstance.getComponentUid());
616 if (resourcefetched != null && resourcefetched.isLeft()) {
617 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
618 if (MapUtils.isNotEmpty(derivedWithId)) {
619 derivedFromMapOfIdToName.putAll(derivedWithId);
624 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
626 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
627 return Optional.ofNullable(derivedFromMapOfIdToName);
631 * Creates a resource map and adds it to the import list.
633 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
634 final Set<Component> componentsList) {
635 componentsList.forEach(component -> setImports(imports, dependencies, component));
638 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
639 final Component component) {
640 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
641 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
642 if (artifactDefinition != null) {
643 final Map<String, String> files = new HashMap<>();
644 final String artifactName = artifactDefinition.getArtifactName();
645 files.put(IMPORTS_FILE_KEY, artifactName);
646 final StringBuilder keyNameBuilder = new StringBuilder();
647 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
648 keyNameBuilder.append("-");
649 keyNameBuilder.append(component.getName());
650 addImports(imports, keyNameBuilder, files);
651 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
652 if (!ModelConverter.isAtomicComponent(component)) {
653 final Map<String, String> interfaceFiles = new HashMap<>();
654 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
655 keyNameBuilder.append("-interface");
656 addImports(imports, keyNameBuilder, interfaceFiles);
662 * Adds the found resource to the import definition list.
664 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
665 final Map<String, String> files) {
666 final String mapKey = keyNameBuilder.toString();
667 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
668 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
669 importsListMember.put(keyNameBuilder.toString(), files);
670 imports.add(importsListMember);
674 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
675 Map<String, ToscaNodeType> nodeTypes) {
676 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
679 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
680 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
681 boolean isAssociatedComponent) {
682 log.debug("start convert node type for {}", component.getUniqueId());
683 ToscaNodeType toscaNodeType = createNodeType(component);
684 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
685 .getAllInterfaceLifecycleTypes();
686 if (lifecycleTypeEither.isRight()) {
687 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
688 return Either.right(ToscaError.GENERAL_ERROR);
690 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
691 .collect(Collectors.toList());
692 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
693 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
694 if (dataTypesEither.isRight()) {
695 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
696 return Either.right(ToscaError.GENERAL_ERROR);
698 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
699 List<InputDefinition> inputDef = component.getInputs();
700 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
701 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
702 addInputsToProperties(dataTypes, inputDef, mergedProperties);
703 final Map<String, ToscaAttribute> toscaAttributeMap;
705 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
706 } catch (final ToscaConversionException e) {
707 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
708 "Could not parse component '{}' attributes. Component unique id '{}'.",
709 new Object[]{component.getName(), component.getUniqueId(), e});
710 return Either.right(ToscaError.GENERAL_ERROR);
712 if (!toscaAttributeMap.isEmpty()) {
713 toscaNodeType.setAttributes(toscaAttributeMap);
715 if (CollectionUtils.isNotEmpty(component.getProperties())) {
716 List<PropertyDefinition> properties = component.getProperties();
717 Map<String, ToscaProperty> convertedProperties = properties.stream()
718 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
719 .toMap(PropertyDataDefinition::getName,
720 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
721 // merge component properties and inputs properties
722 mergedProperties.putAll(convertedProperties);
724 if (MapUtils.isNotEmpty(mergedProperties)) {
725 toscaNodeType.setProperties(mergedProperties);
727 /* convert private data_types */
728 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
729 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
730 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
731 for (DataTypeDefinition dataType : privateDataTypes) {
732 log.debug("Emitting private data type: component.name={} dataType.name={}",
733 component.getNormalizedName(), dataType.getName());
734 ToscaDataType toscaDataType = new ToscaDataType();
735 toscaDataType.setDerived_from(dataType.getDerivedFromName());
736 toscaDataType.setDescription(dataType.getDescription());
737 toscaDataType.setVersion(dataType.getVersion());
738 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
739 toscaDataType.setProperties(dataType.getProperties().stream()
740 .collect(Collectors.toMap(
741 PropertyDataDefinition::getName,
742 s -> propertyConvertor
743 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
746 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
748 toscaNode.setData_types(toscaDataTypeMap);
751 // Extracted to method for code reuse
752 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
755 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
756 final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
757 if (CollectionUtils.isEmpty(attributeList)) {
758 return Collections.emptyMap();
760 final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
761 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
762 for (final AttributeDefinition attributeDefinition : attributeList) {
763 toscaAttributeMap.put(attributeDefinition.getName(), attributeConverter.convert(attributeDefinition));
765 return toscaAttributeMap;
768 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
769 Component component, ToscaTemplate toscaNode,
770 Map<String, ToscaNodeType> nodeTypes,
771 ToscaNodeType toscaNodeType,
772 Map<String, DataTypeDefinition> dataTypes) {
773 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
775 if (capabilities.isRight()) {
776 return Either.right(capabilities.right().value());
778 toscaNodeType = capabilities.left().value();
779 log.debug("Capabilities converted for {}", component.getUniqueId());
781 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
782 .convertRequirements(componentsCache, component,
784 if (requirements.isRight()) {
785 return Either.right(requirements.right().value());
787 toscaNodeType = requirements.left().value();
788 log.debug("Requirements converted for {}", component.getUniqueId());
790 String toscaResourceName;
791 switch (component.getComponentType()) {
793 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
794 .getMetadataDataDefinition()).getToscaResourceName();
797 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
798 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
801 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
802 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
805 nodeTypes.put(toscaResourceName, toscaNodeType);
806 toscaNode.setNode_types(nodeTypes);
807 log.debug("finish convert node type for {}", component.getUniqueId());
808 return Either.left(toscaNode);
811 protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(
813 List<ComponentInstance> componentInstances,
814 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
815 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
816 Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes,
817 ToscaTopolgyTemplate topologyTemplate) {
819 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
820 log.debug("start convert topology template for {} for type {}", component.getUniqueId(),
821 component.getComponentType());
822 Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
823 Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
825 Map<String, ToscaGroupTemplate> groupsMap = null;
826 for (ComponentInstance componentInstance : componentInstances) {
827 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
828 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
829 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
831 nodeTemplate.setType(componentInstance.getToscaComponentName());
832 nodeTemplate.setDirectives(componentInstance.getDirectives());
833 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
835 Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
836 .getOriginComponent(componentCache, componentInstance);
837 if (originComponentRes.isRight()) {
838 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
841 Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component,
842 componentInstance, component.getComponentInstancesRelations(), nodeTemplate,
843 originComponentRes.left().value(), componentCache);
844 if (requirements.isRight()) {
845 convertNodeTemplatesRes = Either.right(requirements.right().value());
848 String instanceUniqueId = componentInstance.getUniqueId();
849 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
851 nodeTemplate = requirements.left().value();
853 Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
855 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
856 Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
857 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
859 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
862 Either<ToscaNodeTemplate, ToscaError> capabilities = capabilityRequirementConverter
863 .convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
864 if (capabilities.isRight()) {
865 convertNodeTemplatesRes = Either.right(capabilities.right().value());
868 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
870 nodeTemplate = capabilities.left().value();
871 Map<String, Object> props = new HashMap<>();
873 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
874 // Adds the properties of parent component to map
875 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
878 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
879 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId,
883 if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)
884 && !isComponentOfTypeServiceProxy(componentInstance)) {
885 //For service proxy the inputs are already handled under instance properties above
886 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
889 //M3[00001] - NODE TEMPLATE INTERFACES - START
890 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate,
891 instanceUniqueId, component);
892 //M3[00001] - NODE TEMPLATE INTERFACES - END
893 if (props != null && !props.isEmpty()) {
894 nodeTemplate.setProperties(props);
897 List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
898 if (groupInstances != null) {
899 if (groupsMap == null) {
900 groupsMap = new HashMap<>();
902 for (GroupInstance groupInst : groupInstances) {
903 boolean addToTosca = true;
905 List<String> artifacts = groupInst.getArtifacts();
906 if (artifacts == null || artifacts.isEmpty()) {
911 ToscaGroupTemplate toscaGroup = groupExportParser
912 .getToscaGroupTemplate(groupInst, componentInstance.getInvariantName());
913 groupsMap.put(groupInst.getName(), toscaGroup);
918 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
920 if (groupsMap != null) {
921 log.debug("instance groups added");
922 topologyTemplate.addGroups(groupsMap);
924 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
925 ((Service) component).getForwardingPaths())) {
926 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(),
927 component.getName());
928 ForwardingPathToscaUtil
929 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache,
930 toscaOperationFacade);
931 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(),
932 component.getName());
934 if (convertNodeTemplatesRes == null) {
935 convertNodeTemplatesRes = Either.left(nodeTemplates);
937 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(),
938 component.getComponentType());
939 return convertNodeTemplatesRes;
942 private void handleInstanceInterfaces(
943 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
944 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
945 String instanceUniqueId,
946 Component parentComponent) {
948 if (MapUtils.isEmpty(componentInstanceInterfaces)
949 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
950 nodeTemplate.setInterfaces(null);
954 final List<ComponentInstanceInterface> currServiceInterfaces =
955 componentInstanceInterfaces.get(instanceUniqueId);
957 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
958 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
959 .getUniqueId(), instInterface));
961 final Map<String, Object> interfaceMap = interfacesOperationsConverter
962 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
963 isComponentOfTypeServiceProxy(componentInstance));
965 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
966 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
969 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
970 return Objects.nonNull(componentInstance.getOriginType())
971 && componentInstance.getOriginType().getValue().equals("Service Proxy");
974 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
975 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
976 String instanceUniqueId, Map<String, Object> props) {
978 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
979 if (instanceInputsList != null) {
980 instanceInputsList.forEach(input -> {
982 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
983 ? input.getValue() : input.getDefaultValue();
984 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
989 private void addPropertiesOfComponentInstance(
990 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
991 Map<String, DataTypeDefinition> dataTypes, String instanceUniqueId,
992 Map<String, Object> props) {
994 if (isNotEmpty(componentInstancesProperties)) {
995 componentInstancesProperties.get(instanceUniqueId)
996 // Converts and adds each value to property map
997 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
1002 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1003 Component componentOfInstance, Map<String, Object> props) {
1005 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1006 if (isNotEmpty(componentProperties)) {
1007 componentProperties.stream()
1008 // Filters out properties with empty default values
1009 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1010 // Converts and adds each value to property map
1011 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
1012 prop::getDefaultValue));
1016 private ToscaNodeType createNodeType(Component component) {
1017 ToscaNodeType toscaNodeType = new ToscaNodeType();
1018 if (ModelConverter.isAtomicComponent(component)) {
1019 if (((Resource) component).getDerivedFrom() != null) {
1020 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1022 toscaNodeType.setDescription(component.getDescription());
1024 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1026 toscaNodeType.setDerived_from(derivedFrom);
1028 return toscaNodeType;
1031 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1033 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1034 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1035 List<ComponentInstance> componentInstances = container.getComponentInstances();
1036 if (CollectionUtils.isEmpty(componentInstances)) {
1039 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1040 componentInstances.stream()
1041 .filter(this::isComponentOfTypeServiceProxy)
1042 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1043 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1046 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1047 Component serviceComponent;
1048 ComponentParametersView componentParametersView = new ComponentParametersView();
1049 componentParametersView.disableAll();
1050 componentParametersView.setIgnoreInterfaces(false);
1051 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1052 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1053 if (service.isRight()) {
1054 log.debug("Failed to fetch original service component with id {} for instance {}",
1055 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1056 return Either.right(ToscaError.GENERAL_ERROR);
1058 serviceComponent = service.left().value();
1061 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1062 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
1063 if (lifecycleTypeEither.isRight()) {
1064 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1065 return Either.right(ToscaError.GENERAL_ERROR);
1068 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1069 .map(InterfaceDataDefinition::getType)
1070 .collect(Collectors.toList());
1071 //Add interface types for local interfaces in the original service component for proxy
1072 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1073 allGlobalInterfaceTypes);
1074 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1075 proxyInterfaceTypes.putAll(localInterfaceTypes);
1079 return Either.left(proxyInterfaceTypes);
1082 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1083 Component container) {
1085 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1086 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1088 List<ComponentInstance> componentInstances = container.getComponentInstances();
1090 if (componentInstances == null || componentInstances.isEmpty()) {
1093 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1094 List<ComponentInstance> proxyInst = componentInstances.stream()
1095 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1096 .collect(Collectors.toList());
1097 if (proxyInst != null && !proxyInst.isEmpty()) {
1098 for (ComponentInstance inst : proxyInst) {
1099 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1103 if (serviceProxyInstanceList.isEmpty()) {
1106 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1107 .getLatestByName("serviceProxy");
1108 if (serviceProxyOrigin.isRight()) {
1109 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1110 serviceProxyOrigin.right().value());
1111 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1113 Component origComponent = serviceProxyOrigin.left().value();
1115 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1116 Component serviceComponent = null;
1117 ComponentParametersView componentParametersView = new ComponentParametersView();
1118 componentParametersView.disableAll();
1119 componentParametersView.setIgnoreCategories(false);
1120 componentParametersView.setIgnoreProperties(false);
1121 componentParametersView.setIgnoreInputs(false);
1122 componentParametersView.setIgnoreInterfaces(false);
1123 componentParametersView.setIgnoreRequirements(false);
1124 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1125 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1126 if (service.isRight()) {
1127 log.debug("Failed to fetch resource with id {} for instance {}",
1128 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1130 serviceComponent = service.left().value();
1133 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1134 entryProxy.getValue());
1135 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1138 return Either.left(nodeTypesMap);
1141 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1142 final Component container, final ToscaTemplate toscaNode) {
1143 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1145 if (CollectionUtils.isEmpty(componentInstances)) {
1148 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1149 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1150 .collect(Collectors.toList());
1151 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1152 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1153 final Map<String, ToscaNodeType> nodeTypes =
1154 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1155 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1161 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1162 Component proxyComponent, ComponentInstance componentInstance) {
1163 ToscaNodeType toscaNodeType = new ToscaNodeType();
1164 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1166 toscaNodeType.setDerived_from(derivedFrom);
1167 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1168 if (dataTypesEither.isRight()) {
1169 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1171 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1172 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1173 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1175 if (MapUtils.isNotEmpty(capabilities)) {
1176 toscaNodeType.setCapabilities(capabilities);
1178 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1179 .convertProxyRequirements(componentCache, componentInstance);
1180 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1181 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1183 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1184 proxyProperties.ifPresent(toscaNodeType::setProperties);
1186 Map<String, Object> interfaceMap = new HashMap<>();
1187 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1188 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1189 if (proxyInterfaces.isPresent()) {
1190 interfaceMap = proxyInterfaces.get();
1193 interfaceMap = interfacesOperationsConverter
1194 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1197 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1198 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1200 return toscaNodeType;
1203 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1204 ComponentInstance componentInstance,
1205 List<RequirementCapabilityRelDef> relations,
1206 ToscaNodeTemplate nodeTypeTemplate,
1207 Component originComponent,
1208 Map<String, Component> componentCache) {
1210 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements;
1211 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1213 if (isNotEmpty(requirementDefinitionList)) {
1215 toscaRequirements = buildRequirements(component, componentInstance,
1216 requirementDefinitionList, originComponent, componentCache);
1217 if (!toscaRequirements.isEmpty()) {
1218 nodeTypeTemplate.setRequirements(toscaRequirements);
1220 } catch (final Exception e) {
1221 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1222 componentInstance.getName(), e);
1223 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1226 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1227 return Either.left(nodeTypeTemplate);
1230 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1231 final ComponentInstance componentInstance,
1232 final List<RequirementCapabilityRelDef> filteredRelations,
1233 final Component originComponent,
1234 final Map<String, Component> componentCache)
1235 throws ToscaExportException {
1237 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1238 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1239 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1240 buildRequirement(componentInstance, originComponent, component.getComponentInstances(),
1241 relationshipDefinition, componentCache);
1242 toscaRequirements.add(toscaTemplateRequirementMap);
1245 return toscaRequirements;
1248 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1249 List<RequirementCapabilityRelDef> relations) {
1250 return relations.stream()
1251 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1254 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1255 final Component fromOriginComponent,
1256 final List<ComponentInstance> instancesList,
1257 final RequirementCapabilityRelDef relationshipDefinition,
1258 final Map<String, Component> componentCache)
1259 throws ToscaExportException {
1261 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1262 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1263 .getRelationships().get(0);
1264 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1266 final ComponentInstance toInstance = instancesList.stream()
1267 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1268 .findFirst().orElse(null);
1269 if (toInstance == null) {
1270 final String errorMsg = String
1271 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1272 relationshipDefinition.getToNode());
1273 log.debug(errorMsg);
1274 throw new ToscaExportException(errorMsg);
1276 final Optional<RequirementDefinition> reqOpt =
1277 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1278 if (reqOpt.isEmpty()) {
1279 final String errorMsg = String
1280 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1281 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1282 log.debug(errorMsg);
1283 throw new ToscaExportException(errorMsg);
1285 final ComponentParametersView filter = new ComponentParametersView(true);
1286 filter.setIgnoreComponentInstances(false);
1287 filter.setIgnoreCapabilities(false);
1288 filter.setIgnoreGroups(false);
1289 final Either<Component, StorageOperationStatus> getOriginRes =
1290 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1291 if (getOriginRes.isRight()) {
1292 final String errorMsg = String.format(
1293 "Failed to build substituted name for the requirement %s. "
1294 + "Failed to get an origin component with uniqueId %s",
1295 reqOpt.get().getName(), toInstance.getActualComponentUid());
1296 log.debug(errorMsg);
1297 throw new ToscaExportException(errorMsg);
1299 final Component toOriginComponent = getOriginRes.left().value();
1300 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1301 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1302 if (capOpt.isEmpty()) {
1303 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1304 if (capOpt.isEmpty()) {
1305 final String errorMsg = String
1306 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1307 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1308 log.debug(errorMsg);
1309 throw new ToscaExportException(errorMsg);
1312 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1313 capabilityRequirementRelationship, toInstance, componentCache);
1316 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1317 CapabilityDefinition capability) {
1318 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1319 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1322 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1323 Component toOriginComponent, Component fromOriginComponent,
1324 RequirementDefinition requirement) {
1325 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1326 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1327 if (!cap.isPresent()) {
1328 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1329 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1334 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1335 final Component toOriginComponent,
1336 final CapabilityDefinition capability,
1337 final RequirementDefinition requirement,
1338 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1339 final ComponentInstance toInstance,
1340 final Map<String, Component> componentCache)
1341 throws ToscaExportException {
1343 List<String> reducedPath = capability.getPath();
1344 if (capability.getOwnerId() != null) {
1345 reducedPath = capabilityRequirementConverter
1346 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1348 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1349 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1350 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1351 if (capabilityNameEither.isRight()) {
1352 final String errorMsg = String.format(
1353 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1354 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1357 throw new ToscaExportException(errorMsg);
1359 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1360 .buildSubstitutedName(componentCache, fromOriginComponent,
1361 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1362 if (requirementNameEither.isRight()) {
1363 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1364 + "with name %s on a component with uniqueId %s",
1365 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1366 log.debug(errorMsg);
1367 throw new ToscaExportException(errorMsg);
1369 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1370 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1371 toscaRequirement.setNode(toInstance.getName());
1372 toscaRequirement.setCapability(capabilityNameEither.left().value());
1373 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1374 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1376 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1380 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1381 Map<String, List<RequirementDefinition>> reqMap,
1382 RelationshipInfo reqAndRelationshipPair,
1383 String fromInstanceId) {
1384 for (List<RequirementDefinition> reqList : reqMap.values()) {
1385 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1386 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1388 if (reqOpt.isPresent()) {
1392 return Optional.empty();
1396 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1397 * 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
1398 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1400 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1401 RequirementDefinition requirement, String fromInstanceId) {
1402 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1403 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1404 reqAndRelationshipPair.getRequirement());
1407 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1411 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1412 Component originComponent) {
1413 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1414 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1415 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1418 private boolean isCvfc(Component component) {
1419 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1422 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1423 Map<String, Component> componentCache) {
1424 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1425 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1426 .convertSubstitutionMappingCapabilities(componentCache, component);
1427 if (toscaCapabilitiesRes.isRight()) {
1428 result = Either.right(toscaCapabilitiesRes.right().value());
1429 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1430 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1431 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1432 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1434 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1438 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1439 Map<String, DataTypeDefinition> dataTypes) {
1440 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1441 if (!toscaCapabilities.isEmpty()) {
1442 nodeType.setCapabilities(toscaCapabilities);
1444 log.debug("Finish convert Capabilities for node type");
1445 return Either.left(nodeType);
1448 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1449 if (artifacts == null) {
1452 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1453 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1454 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1455 artifact.setFile(entry.getValue().getFile());
1456 artifact.setType(entry.getValue().getType());
1457 arts.put(entry.getKey(), artifact);
1462 protected NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1463 if (inNodeFilter == null) {
1466 NodeFilter nodeFilter = new NodeFilter();
1467 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1468 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1469 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1470 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1471 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1472 copyNodeFilterProperties(origProperties, propertiesCopy);
1473 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1474 nodeFilter.setCapabilities(capabilitiesCopy);
1476 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1477 nodeFilter.setProperties(propertiesCopy);
1479 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1480 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1484 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1485 if (substitutionFilterDataDefinition == null) {
1488 NodeFilter nodeFilter = new NodeFilter();
1489 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1490 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1491 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1492 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1493 nodeFilter.setProperties(propertiesCopy);
1495 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1496 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1499 private Object cloneToscaId(Object toscaId) {
1500 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1503 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1504 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1505 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1508 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1509 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1510 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1514 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1515 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1516 CapabilityFilter capabilityFilter = new CapabilityFilter();
1517 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1518 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1519 capabilityFilter.setProperties(propertiesCopy);
1520 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1521 capabilitiesCopy.add(capabilityFilterCopyMap);
1525 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1526 List<Map<String, List<Object>>> propertiesCopy) {
1527 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1530 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1531 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1532 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1533 Map propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1534 String propertyName = propertyDataDefinition.getName();
1535 if (propertyMapCopy.containsKey(propertyName)) {
1536 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1538 if (propertyName != null) {
1539 List<Object> propsList = new ArrayList<>();
1540 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1541 propertyMapCopy.put(propertyName, propsList);
1543 propertyMapCopy.putAll(propertyValObj);
1548 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1551 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1552 final List<Map<String, List<Object>>> propertiesCopy) {
1553 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1556 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1557 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1558 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1559 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1560 final String propertyName = propertyDataDefinition.getName();
1561 if (propertyMapCopy.containsKey(propertyName)) {
1562 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1564 if (propertyName != null) {
1565 final List<Object> propsList = new ArrayList<>();
1566 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1567 propertyMapCopy.put(propertyName, propsList);
1569 propertyMapCopy.putAll(propertyValObj);
1574 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1577 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1578 if (propertyValObj.containsKey(propertyName)) {
1579 propsList.add(propertyValObj.get(propertyName));
1581 propsList.add(propertyValObj);
1585 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1586 Map<String, List<Object>> tempMap = new HashMap<>();
1587 tempMap.put(entry.getKey(), entry.getValue());
1588 propertiesCopy.add(tempMap);
1591 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1592 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1593 return Collections.emptyMap();
1595 return component.getInputs().stream().filter(input -> input.isMappedToComponentProperty()).map(PropertyDataDefinition::getName)
1596 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1599 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1600 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1601 return Collections.emptyMap();
1603 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1604 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1607 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1608 if (Objects.isNull(proxyComponent)) {
1609 return Optional.empty();
1611 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1612 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1613 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1614 proxyProperties.putAll(proxyComponent.getProperties().stream()
1615 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1616 .toMap(PropertyDataDefinition::getName,
1617 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1619 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1622 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1623 Map<String, ToscaProperty> mergedProperties) {
1624 if (CollectionUtils.isEmpty(componentInputs)) {
1627 for (InputDefinition input : componentInputs) {
1628 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1629 mergedProperties.put(input.getName(), property);
1633 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1634 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1635 return Optional.empty();
1637 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1638 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1640 // always available in the proxy node template
1641 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1643 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1646 private static class CustomRepresenter extends Representer {
1648 CustomRepresenter() {
1650 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1651 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1652 // null representer is exceptional and it is stored as an instance
1655 this.nullRepresenter = new RepresentNull();
1658 public boolean validateGetInputValue(final Object valueObj) {
1659 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1662 if (valueObj instanceof List) {
1663 return ((List) valueObj).size() > 1;
1668 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1669 if (valueObj instanceof List) {
1670 return ((List) valueObj).size() > 1;
1676 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1677 if (propertyValue == null) {
1680 // skip not relevant for Tosca property
1681 if ("dependencies".equals(property.getName())) {
1684 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1687 removeDefaultP(propertyValue);
1688 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1689 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1690 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1692 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1695 private void removeDefaultP(final Object propertyValue) {
1696 if (propertyValue instanceof Map) {
1697 final Map mapPropertyValue = ((Map) propertyValue);
1698 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1699 Object defaultValue = null;
1700 while (iter.hasNext()) {
1701 final Map.Entry entry = iter.next();
1702 if ("_defaultp_".equals(entry.getKey())) {
1703 defaultValue = entry.getValue();
1705 } else if (entry.getValue() instanceof Map) {
1706 removeDefaultP(entry.getValue());
1709 if (defaultValue != null) {
1710 mapPropertyValue.putIfAbsent("default", defaultValue);
1716 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1717 // remove the bean type from the output yaml (!! ...)
1718 if (!classTags.containsKey(javaBean.getClass())) {
1719 addClassTag(javaBean.getClass(), Tag.MAP);
1721 return super.representJavaBean(properties, javaBean);
1724 private class RepresentToscaAttribute implements Represent {
1727 public Node representData(Object data) {
1728 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1729 return represent(toscaAttribute.asToscaMap());
1733 private class RepresentToscaPropertyAssignment implements Represent {
1735 public Node representData(Object data) {
1736 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1737 if (toscaOperationAssignment.getValue() instanceof String) {
1738 final String stringValue = (String) toscaOperationAssignment.getValue();
1739 if (isPropertyOrAttributeFunction(stringValue)) {
1740 return representGetAttribute(stringValue);
1742 return representScalar(Tag.STR, stringValue);
1744 return represent(null);
1747 public Node representGetAttribute(final String getAttributeFunction) {
1748 return represent(new Yaml().load(getAttributeFunction));
1751 public boolean isPropertyOrAttributeFunction(final String value) {
1753 final Yaml yaml = new Yaml();
1754 final Object yamlObj = yaml.load(value);
1755 if (!(yamlObj instanceof Map)) {
1758 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1759 if (getAttributeMap.size() != 1) {
1762 final List<String> functionList = Arrays
1763 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1764 final Optional<String> function = getAttributeMap.keySet().stream()
1765 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1766 if (function.isEmpty()) {
1769 final String functionName = function.get();
1770 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1771 if (GET_INPUT.getFunctionName().equals(functionName)) {
1772 return validateGetInputValue(getAttributeValueObj);
1774 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1776 } catch (final Exception ignored) {
1782 private class RepresentNull implements Represent {
1785 public Node representData(Object data) {
1786 // possible values are here http://yaml.org/type/null.html
1787 return representScalar(Tag.NULL, "");
1792 private static class UnsortedPropertyUtils extends PropertyUtils {
1795 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1796 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1797 return new LinkedHashSet<>(fields);