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.Configuration;
57 import org.openecomp.sdc.be.config.ConfigurationManager;
58 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
59 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
60 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
70 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
71 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
72 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
73 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
74 import org.openecomp.sdc.be.exception.ToscaExportException;
75 import org.openecomp.sdc.be.model.ArtifactDefinition;
76 import org.openecomp.sdc.be.model.AttributeDefinition;
77 import org.openecomp.sdc.be.model.CapabilityDefinition;
78 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
79 import org.openecomp.sdc.be.model.Component;
80 import org.openecomp.sdc.be.model.ComponentInstance;
81 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
82 import org.openecomp.sdc.be.model.ComponentInstanceInput;
83 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
84 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
85 import org.openecomp.sdc.be.model.ComponentParametersView;
86 import org.openecomp.sdc.be.model.DataTypeDefinition;
87 import org.openecomp.sdc.be.model.GroupInstance;
88 import org.openecomp.sdc.be.model.InputDefinition;
89 import org.openecomp.sdc.be.model.InterfaceDefinition;
90 import org.openecomp.sdc.be.model.PropertyDefinition;
91 import org.openecomp.sdc.be.model.RelationshipInfo;
92 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
93 import org.openecomp.sdc.be.model.RequirementDefinition;
94 import org.openecomp.sdc.be.model.Resource;
95 import org.openecomp.sdc.be.model.Service;
96 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
97 import org.openecomp.sdc.be.model.category.CategoryDefinition;
98 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
99 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
100 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
101 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
102 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
103 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
104 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
105 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
106 import org.openecomp.sdc.be.tosca.model.NodeFilter;
107 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
108 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
109 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
110 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
111 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
112 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
113 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
114 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
115 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
116 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
117 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
118 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
119 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
120 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
121 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
122 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
123 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
124 import org.openecomp.sdc.be.tosca.utils.InputConverter;
125 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
126 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
127 import org.openecomp.sdc.common.log.wrappers.Logger;
128 import org.springframework.beans.factory.annotation.Autowired;
129 import org.yaml.snakeyaml.DumperOptions;
130 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
131 import org.yaml.snakeyaml.Yaml;
132 import org.yaml.snakeyaml.introspector.BeanAccess;
133 import org.yaml.snakeyaml.introspector.Property;
134 import org.yaml.snakeyaml.introspector.PropertyUtils;
135 import org.yaml.snakeyaml.nodes.MappingNode;
136 import org.yaml.snakeyaml.nodes.Node;
137 import org.yaml.snakeyaml.nodes.NodeTuple;
138 import org.yaml.snakeyaml.nodes.Tag;
139 import org.yaml.snakeyaml.representer.Represent;
140 import org.yaml.snakeyaml.representer.Representer;
143 @org.springframework.stereotype.Component("tosca-export-handler")
144 public class ToscaExportHandler {
146 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
147 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
148 private static final String INVARIANT_UUID = "invariantUUID";
149 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
150 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
151 private static final String IMPORTS_FILE_KEY = "file";
152 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
153 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
154 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
155 private static final String NATIVE_ROOT = "tosca.nodes.Root";
156 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
157 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
158 private static final YamlUtil yamlUtil = new YamlUtil();
159 private static final String COULD_NOT_PARSE_COMPONENT_ATTRIBUTES_COMPONENT_UNIQUE_ID = "Could not parse component '{}' attributes. Component unique id '{}'.";
160 private ApplicationDataTypeCache dataTypeCache;
161 private ToscaOperationFacade toscaOperationFacade;
162 private CapabilityRequirementConverter capabilityRequirementConverter;
163 private PolicyExportParser policyExportParser;
164 private GroupExportParser groupExportParser;
165 private PropertyConvertor propertyConvertor;
166 private AttributeConverter attributeConverter;
167 private InputConverter inputConverter;
168 private OutputConverter outputConverter;
169 private InterfaceLifecycleOperation interfaceLifecycleOperation;
170 private InterfacesOperationsConverter interfacesOperationsConverter;
173 public ToscaExportHandler(final ApplicationDataTypeCache dataTypeCache,
174 final ToscaOperationFacade toscaOperationFacade,
175 final CapabilityRequirementConverter capabilityRequirementConverter,
176 final PolicyExportParser policyExportParser,
177 final GroupExportParser groupExportParser,
178 final PropertyConvertor propertyConvertor,
179 final AttributeConverter attributeConverter,
180 final InputConverter inputConverter,
181 final OutputConverter outputConverter,
182 final InterfaceLifecycleOperation interfaceLifecycleOperation,
183 final InterfacesOperationsConverter interfacesOperationsConverter) {
184 this.dataTypeCache = dataTypeCache;
185 this.toscaOperationFacade = toscaOperationFacade;
186 this.capabilityRequirementConverter = capabilityRequirementConverter;
187 this.policyExportParser = policyExportParser;
188 this.groupExportParser = groupExportParser;
189 this.propertyConvertor = propertyConvertor;
190 this.attributeConverter = attributeConverter;
191 this.inputConverter = inputConverter;
192 this.outputConverter = outputConverter;
193 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
194 this.interfacesOperationsConverter = interfacesOperationsConverter;
197 public static String getInterfaceFilename(String artifactName) {
198 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
201 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
202 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
205 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
206 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
209 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
210 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
213 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
214 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImportConfig());
215 if (CollectionUtils.isEmpty(imports)) {
216 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
217 return Either.right(ToscaError.GENERAL_ERROR);
219 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
220 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
221 .startsWith("org.openecomp.resource.abstract.nodes.")) {
222 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
223 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion());
224 if (baseType.isLeft() && baseType.left().value() != null) {
225 addDependencies(imports, dependencies, baseType.left().value());
227 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
231 String toscaVersion = null;
232 if (component instanceof Resource) {
233 toscaVersion = ((Resource) component).getToscaVersion();
235 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
236 toscaTemplate.setImports(imports);
237 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
238 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
239 isAssociatedComponent);
240 if (toscaTemplateRes.isRight()) {
241 return Either.right(toscaTemplateRes.right().value());
243 toscaTemplate = toscaTemplateRes.left().value();
244 toscaTemplate.setDependencies(dependencies);
245 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
246 return Either.left(toscaRepresentation);
249 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
250 CustomRepresenter representer = new CustomRepresenter();
251 DumperOptions options = new DumperOptions();
252 options.setAllowReadOnlyProperties(false);
253 options.setPrettyFlow(true);
254 options.setDefaultFlowStyle(FlowStyle.FLOW);
255 options.setCanonical(false);
256 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
257 representer.setPropertyUtils(new UnsortedPropertyUtils());
258 Yaml yaml = new Yaml(representer, options);
259 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
260 StringBuilder sb = new StringBuilder();
261 sb.append(getConfiguration().getHeatEnvArtifactHeader());
262 sb.append(yamlAsString);
263 sb.append(getConfiguration().getHeatEnvArtifactFooter());
264 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
267 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
268 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
269 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
270 if (fillImports.isRight()) {
271 return Either.right(fillImports.right().value());
273 return Either.left(fillImports.left().value().left);
276 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
277 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
278 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
279 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
280 return Either.right(ToscaError.GENERAL_ERROR);
282 log.trace("start tosca export for {}", component.getUniqueId());
283 String toscaVersion = null;
284 if (component instanceof Resource) {
285 toscaVersion = ((Resource) component).getToscaVersion();
287 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
288 toscaTemplate.setMetadata(convertMetadata(component));
289 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
290 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
291 if (ModelConverter.isAtomicComponent(component)) {
292 log.trace("convert component as node type");
293 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
295 log.trace("convert component as topology template");
296 return convertToscaTemplate(component, toscaTemplate);
300 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
301 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
302 if (importsRes.isRight()) {
303 return Either.right(importsRes.right().value());
305 toscaNode = importsRes.left().value().left;
306 Map<String, Component> componentCache = importsRes.left().value().right;
307 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
308 if (nodeTypesMapEither.isRight()) {
309 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
310 return Either.right(nodeTypesMapEither.right().value());
312 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
313 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
314 toscaNode.setNode_types(nodeTypesMap);
316 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
317 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
318 if (proxyInterfaceTypesEither.isRight()) {
319 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
320 return Either.right(proxyInterfaceTypesEither.right().value());
322 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
323 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
324 toscaNode.setInterface_types(proxyInterfaceTypes);
326 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
327 if (dataTypesEither.isRight()) {
328 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
329 return Either.right(ToscaError.GENERAL_ERROR);
331 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
332 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
333 List<InputDefinition> inputDef = component.getInputs();
334 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
335 if (!inputs.isEmpty()) {
336 topologyTemplate.setInputs(inputs);
338 final Map<String, ToscaProperty> outputs;
340 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
341 } catch (final ToscaConversionException e) {
342 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
343 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
344 return Either.right(ToscaError.GENERAL_ERROR);
346 if (!outputs.isEmpty()) {
347 topologyTemplate.setOutputs(outputs);
349 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
350 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
351 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
352 if (nodeTemplates.isRight()) {
353 return Either.right(nodeTemplates.right().value());
355 log.debug("node templates converted");
356 topologyTemplate.setNode_templates(nodeTemplates.left().value());
358 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
359 .createFrom(topologyTemplate.getNode_templates());
360 if (!relationshipTemplatesMap.isEmpty()) {
361 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
363 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
364 convertSubstitutionMappingFilter(component, substitutionMapping);
365 addGroupsToTopologyTemplate(component, topologyTemplate);
367 addPoliciesToTopologyTemplate(component, topologyTemplate);
368 } catch (SdcResourceNotFoundException e) {
369 log.debug("Fail to add policies to topology template:", e);
370 return Either.right(ToscaError.GENERAL_ERROR);
372 String toscaResourceName;
373 switch (component.getComponentType()) {
375 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
376 .getToscaResourceName();
379 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
382 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
383 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
385 substitutionMapping.setNode_type(toscaResourceName);
386 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
387 if (capabilities.isRight()) {
388 return Either.right(capabilities.right().value());
390 substitutionMapping = capabilities.left().value();
391 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
392 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
393 if (requirements.isRight()) {
394 return Either.right(requirements.right().value());
396 substitutionMapping = requirements.left().value();
397 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
398 if (!propertyMappingMap.isEmpty()) {
399 substitutionMapping.setProperties(propertyMappingMap);
401 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
402 if (!attributesMappingMap.isEmpty()) {
403 substitutionMapping.setAttributes(attributesMappingMap);
405 topologyTemplate.setSubstitution_mappings(substitutionMapping);
406 toscaNode.setTopology_template(topologyTemplate);
407 return Either.left(toscaNode);
410 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
411 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
412 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
416 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
417 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
418 if (groups != null) {
419 topologyTemplate.addGroups(groups);
423 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
424 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
425 if (policies != null) {
426 topologyTemplate.addPolicies(policies);
430 private Map<String, String> convertMetadata(Component component) {
431 return convertMetadata(component, false, null);
434 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
435 Map<String, String> toscaMetadata = new LinkedHashMap<>();
436 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
437 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
439 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
440 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
441 List<CategoryDefinition> categories = component.getCategories();
442 CategoryDefinition categoryDefinition = categories.get(0);
443 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
445 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
446 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
447 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
448 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
449 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
450 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
451 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
452 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
453 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
454 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
455 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
456 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
457 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
459 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
462 switch (component.getComponentType()) {
464 Resource resource = (Resource) component;
465 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
466 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
467 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
469 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
471 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
472 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
473 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
474 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
477 Service service = (Service) component;
478 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
479 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
480 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
481 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
482 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
483 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
484 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
487 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
488 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
489 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
493 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
495 for (final String key : component.getCategorySpecificMetadata().keySet()) {
496 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
497 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
500 return toscaMetadata;
503 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
504 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
505 return INVARIANT_UUID;
507 return jsonPresentationField.getPresentation();
510 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
511 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
512 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
513 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
514 return Either.right(ToscaError.GENERAL_ERROR);
516 Map<String, Component> componentCache = new HashMap<>();
517 if (!ModelConverter.isAtomicComponent(component)) {
518 final List<Map<String, Map<String, String>>> additionalImports =
519 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
520 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
521 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
522 if (isNotEmpty(toscaArtifacts)) {
523 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
524 if (artifactDefinition != null) {
525 Map<String, Map<String, String>> importsListMember = new HashMap<>();
526 Map<String, String> interfaceFiles = new HashMap<>();
527 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
528 StringBuilder keyNameBuilder = new StringBuilder();
529 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
530 .append("-interface");
531 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
532 additionalImports.add(importsListMember);
535 List<ComponentInstance> componentInstances = component.getComponentInstances();
536 if (componentInstances != null && !componentInstances.isEmpty()) {
537 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
539 toscaTemplate.setDependencies(dependencies);
540 toscaTemplate.setImports(additionalImports);
542 log.debug("currently imports supported for VF and service only");
544 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
547 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
548 return getConfiguration().getDefaultImports();
551 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
552 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
553 log.debug("createDependency componentCache {}", componentCache);
554 Component componentRI = componentCache.get(componentInstance.getComponentUid());
555 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
556 // all resource must be only once!
557 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
558 if ((resource.isRight()) && (log.isDebugEnabled())) {
559 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
560 componentInstance.getUniqueId());
563 final Component fetchedComponent = resource.left().value();
564 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
565 addDependencies(imports, dependencies, componentRI);
570 * Sets a componentCache from the given component/resource.
572 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
573 final Component fetchedComponent) {
574 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
575 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
576 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
577 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
578 .getToscaFullElement(componentInstance.getSourceModelUid());
579 if (sourceService.isRight() && (log.isDebugEnabled())) {
580 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
581 componentInstance.getUniqueId());
583 final Component fetchedSource = sourceService.left().value();
584 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
585 return fetchedSource;
587 return fetchedComponent;
591 * Retrieves all derived_from nodes and stores it in a predictable order.
593 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
594 final Component fetchedComponent) {
595 final Set<Component> componentsList = new LinkedHashSet<>();
596 if (fetchedComponent instanceof Resource) {
597 log.debug("fetchedComponent is a resource {}", fetchedComponent);
598 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
599 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
600 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
601 log.debug("Started entry.getValue() : {}", entry.getValue());
602 if (!NATIVE_ROOT.equals(entry.getValue())) {
603 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
604 if (resourcefetched != null && resourcefetched.isLeft()) {
605 componentsList.add(resourcefetched.left().value());
609 setImports(imports, dependencies, componentsList);
611 setImports(imports, dependencies, fetchedComponent);
617 * Returns all derived_from nodes found.
619 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
620 final Resource parentResource = (Resource) fetchedComponent;
621 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
622 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
623 componentsList.add(fetchedComponent);
624 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
625 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
626 .getToscaElement(componentInstance.getComponentUid());
627 if (resourcefetched != null && resourcefetched.isLeft()) {
628 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
629 if (MapUtils.isNotEmpty(derivedWithId)) {
630 derivedFromMapOfIdToName.putAll(derivedWithId);
635 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
637 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
638 return Optional.ofNullable(derivedFromMapOfIdToName);
642 * Creates a resource map and adds it to the import list.
644 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
645 final Set<Component> componentsList) {
646 componentsList.forEach(component -> setImports(imports, dependencies, component));
649 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
650 final Component component) {
651 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
652 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
653 if (artifactDefinition != null) {
654 final Map<String, String> files = new HashMap<>();
655 final String artifactName = artifactDefinition.getArtifactName();
656 files.put(IMPORTS_FILE_KEY, artifactName);
657 final StringBuilder keyNameBuilder = new StringBuilder();
658 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
659 keyNameBuilder.append("-");
660 keyNameBuilder.append(component.getName());
661 addImports(imports, keyNameBuilder, files);
662 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
663 if (!ModelConverter.isAtomicComponent(component)) {
664 final Map<String, String> interfaceFiles = new HashMap<>();
665 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
666 keyNameBuilder.append("-interface");
667 addImports(imports, keyNameBuilder, interfaceFiles);
673 * Adds the found resource to the import definition list.
675 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
676 final Map<String, String> files) {
677 final String mapKey = keyNameBuilder.toString();
678 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
679 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
680 importsListMember.put(keyNameBuilder.toString(), files);
681 imports.add(importsListMember);
685 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
686 Map<String, ToscaNodeType> nodeTypes) {
687 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
690 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
691 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
692 boolean isAssociatedComponent) {
693 log.debug("start convert node type for {}", component.getUniqueId());
694 ToscaNodeType toscaNodeType = createNodeType(component);
695 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
696 .getAllInterfaceLifecycleTypes();
697 if (lifecycleTypeEither.isRight()) {
698 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
699 return Either.right(ToscaError.GENERAL_ERROR);
701 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
702 .collect(Collectors.toList());
703 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
704 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
705 if (dataTypesEither.isRight()) {
706 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
707 return Either.right(ToscaError.GENERAL_ERROR);
709 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
710 List<InputDefinition> inputDef = component.getInputs();
711 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
712 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
713 addInputsToProperties(dataTypes, inputDef, mergedProperties);
714 final Map<String, ToscaAttribute> toscaAttributeMap;
716 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
717 } catch (final ToscaConversionException e) {
718 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
719 COULD_NOT_PARSE_COMPONENT_ATTRIBUTES_COMPONENT_UNIQUE_ID, component.getName(), component.getUniqueId(), e);
720 return Either.right(ToscaError.GENERAL_ERROR);
722 if (!toscaAttributeMap.isEmpty()) {
723 toscaNodeType.setAttributes(toscaAttributeMap);
725 if (CollectionUtils.isNotEmpty(component.getProperties())) {
726 List<PropertyDefinition> properties = component.getProperties();
727 Map<String, ToscaProperty> convertedProperties = properties.stream()
728 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
729 .toMap(PropertyDataDefinition::getName,
730 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
731 // merge component properties and inputs properties
732 mergedProperties.putAll(convertedProperties);
734 if (MapUtils.isNotEmpty(mergedProperties)) {
735 toscaNodeType.setProperties(mergedProperties);
737 /* convert private data_types */
738 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
739 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
740 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
741 for (DataTypeDefinition dataType : privateDataTypes) {
742 log.debug("Emitting private data type: component.name={} dataType.name={}",
743 component.getNormalizedName(), dataType.getName());
744 ToscaDataType toscaDataType = new ToscaDataType();
745 toscaDataType.setDerived_from(dataType.getDerivedFromName());
746 toscaDataType.setDescription(dataType.getDescription());
747 toscaDataType.setVersion(dataType.getVersion());
748 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
749 toscaDataType.setProperties(dataType.getProperties().stream()
750 .collect(Collectors.toMap(
751 PropertyDataDefinition::getName,
752 s -> propertyConvertor
753 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
756 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
758 toscaNode.setData_types(toscaDataTypeMap);
761 // Extracted to method for code reuse
762 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
765 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
766 final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
767 if (CollectionUtils.isEmpty(attributeList)) {
768 return Collections.emptyMap();
770 final AttributeConverter converter = new AttributeConverter(dataTypes);
771 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
772 for (final AttributeDefinition attributeDefinition : attributeList) {
773 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
775 return toscaAttributeMap;
778 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
779 Component component, ToscaTemplate toscaNode,
780 Map<String, ToscaNodeType> nodeTypes,
781 ToscaNodeType toscaNodeType,
782 Map<String, DataTypeDefinition> dataTypes) {
783 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
785 if (capabilities.isRight()) {
786 return Either.right(capabilities.right().value());
788 toscaNodeType = capabilities.left().value();
789 log.debug("Capabilities converted for {}", component.getUniqueId());
791 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
792 .convertRequirements(componentsCache, component, toscaNodeType);
793 if (requirements.isRight()) {
794 return Either.right(requirements.right().value());
796 toscaNodeType = requirements.left().value();
797 log.debug("Requirements converted for {}", component.getUniqueId());
799 String toscaResourceName;
800 switch (component.getComponentType()) {
802 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
803 .getMetadataDataDefinition()).getToscaResourceName();
806 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
807 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
810 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
811 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
814 nodeTypes.put(toscaResourceName, toscaNodeType);
815 toscaNode.setNode_types(nodeTypes);
816 log.debug("finish convert node type for {}", component.getUniqueId());
817 return Either.left(toscaNode);
820 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
821 final Map<String, Component> componentCache,
822 final Map<String, DataTypeDefinition> dataTypes,
823 final ToscaTopolgyTemplate topologyTemplate) {
825 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
826 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
827 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
828 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
829 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
831 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
832 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
833 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
835 Map<String, ToscaGroupTemplate> groupsMap = null;
836 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
837 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
838 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
839 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
841 nodeTemplate.setType(componentInstance.getToscaComponentName());
842 nodeTemplate.setDirectives(componentInstance.getDirectives());
843 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
845 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
846 .getOriginComponent(componentCache, componentInstance);
847 if (originComponentRes.isRight()) {
848 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
851 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
852 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
853 if (requirements.isRight()) {
854 convertNodeTemplatesRes = Either.right(requirements.right().value());
857 final String instanceUniqueId = componentInstance.getUniqueId();
858 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
860 nodeTemplate = requirements.left().value();
862 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
864 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
865 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
866 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
868 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
871 final Either<ToscaNodeTemplate, ToscaError> capabilities =
872 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
873 if (capabilities.isRight()) {
874 convertNodeTemplatesRes = Either.right(capabilities.right().value());
877 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
879 nodeTemplate = capabilities.left().value();
880 final Map<String, Object> props = new HashMap<>();
881 final Map<String, Object> attribs = new HashMap<>();
883 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
884 // Adds the properties of parent component to map
885 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
886 addAttributesOfParentComponent(originalComponent, attribs);
889 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
890 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
892 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
893 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
896 if (componentInstancesInputs != null
897 && componentInstancesInputs.containsKey(instanceUniqueId)
898 && !isComponentOfTypeServiceProxy(componentInstance)) {
899 //For service proxy the inputs are already handled under instance properties above
900 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
903 //M3[00001] - NODE TEMPLATE INTERFACES - START
904 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
905 //M3[00001] - NODE TEMPLATE INTERFACES - END
906 if (MapUtils.isNotEmpty(props)) {
907 nodeTemplate.setProperties(props);
909 if (MapUtils.isNotEmpty(attribs)) {
910 nodeTemplate.setAttributes(attribs);
913 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
914 if (CollectionUtils.isNotEmpty(groupInstances)) {
915 if (groupsMap == null) {
916 groupsMap = new HashMap<>();
918 for (final GroupInstance groupInst : groupInstances) {
919 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
920 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
925 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
927 if (groupsMap != null) {
928 log.debug("instance groups added");
929 topologyTemplate.addGroups(groupsMap);
931 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
932 ((Service) component).getForwardingPaths())) {
933 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
934 ForwardingPathToscaUtil
935 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
936 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
938 if (convertNodeTemplatesRes == null) {
939 convertNodeTemplatesRes = Either.left(nodeTemplates);
941 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
942 return convertNodeTemplatesRes;
945 private void handleInstanceInterfaces(
946 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
947 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
948 String instanceUniqueId,
949 Component parentComponent) {
951 if (MapUtils.isEmpty(componentInstanceInterfaces)
952 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
953 nodeTemplate.setInterfaces(null);
957 final List<ComponentInstanceInterface> currServiceInterfaces =
958 componentInstanceInterfaces.get(instanceUniqueId);
960 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
961 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
962 .getUniqueId(), instInterface));
964 final Map<String, Object> interfaceMap = interfacesOperationsConverter
965 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
966 isComponentOfTypeServiceProxy(componentInstance));
968 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
969 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
972 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
973 return Objects.nonNull(componentInstance.getOriginType())
974 && componentInstance.getOriginType().getValue().equals("Service Proxy");
977 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
978 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
979 String instanceUniqueId, Map<String, Object> props) {
981 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
982 if (instanceInputsList != null) {
983 instanceInputsList.forEach(input -> {
985 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
986 ? input.getValue() : input.getDefaultValue();
987 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
992 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
993 final Map<String, DataTypeDefinition> dataTypes,
994 final String instanceUniqueId,
995 final Map<String, Object> props) {
997 if (isNotEmpty(componentInstancesProperties)) {
998 componentInstancesProperties.get(instanceUniqueId)
999 // Converts and adds each value to property map
1000 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1004 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1005 final String instanceUniqueId,
1006 final Map<String, Object> attribs) {
1008 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1009 componentInstancesAttributes.get(instanceUniqueId).stream()
1010 // Filters out Attributes with empty default values
1011 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1012 // Converts and adds each value to attribute map
1013 .forEach(attributeDefinition -> {
1014 attributeConverter.convertAndAddValue(attribs, attributeDefinition);
1019 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1020 Component componentOfInstance, Map<String, Object> props) {
1022 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1023 if (isNotEmpty(componentProperties)) {
1024 componentProperties.stream()
1025 // Filters out properties with empty default values
1026 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1027 // Converts and adds each value to property map
1028 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1032 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1034 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1035 if (isNotEmpty(componentAttributes)) {
1036 componentAttributes.stream()
1037 // Filters out Attributes with empty default values
1038 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1039 // Converts and adds each value to attribute map
1040 .forEach(attributeDefinition -> {
1041 attributeConverter.convertAndAddValue(attribs, attributeDefinition);
1046 private ToscaNodeType createNodeType(Component component) {
1047 ToscaNodeType toscaNodeType = new ToscaNodeType();
1048 if (ModelConverter.isAtomicComponent(component)) {
1049 if (((Resource) component).getDerivedFrom() != null) {
1050 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1052 toscaNodeType.setDescription(component.getDescription());
1054 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1056 toscaNodeType.setDerived_from(derivedFrom);
1058 return toscaNodeType;
1061 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1063 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1064 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1065 List<ComponentInstance> componentInstances = container.getComponentInstances();
1066 if (CollectionUtils.isEmpty(componentInstances)) {
1069 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1070 componentInstances.stream()
1071 .filter(this::isComponentOfTypeServiceProxy)
1072 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1073 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1076 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1077 Component serviceComponent;
1078 ComponentParametersView componentParametersView = new ComponentParametersView();
1079 componentParametersView.disableAll();
1080 componentParametersView.setIgnoreInterfaces(false);
1081 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1082 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1083 if (service.isRight()) {
1084 log.debug("Failed to fetch original service component with id {} for instance {}",
1085 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1086 return Either.right(ToscaError.GENERAL_ERROR);
1088 serviceComponent = service.left().value();
1091 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1092 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
1093 if (lifecycleTypeEither.isRight()) {
1094 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1095 return Either.right(ToscaError.GENERAL_ERROR);
1098 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1099 .map(InterfaceDataDefinition::getType)
1100 .collect(Collectors.toList());
1101 //Add interface types for local interfaces in the original service component for proxy
1102 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1103 allGlobalInterfaceTypes);
1104 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1105 proxyInterfaceTypes.putAll(localInterfaceTypes);
1109 return Either.left(proxyInterfaceTypes);
1112 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1113 Component container) {
1115 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1116 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1118 List<ComponentInstance> componentInstances = container.getComponentInstances();
1120 if (componentInstances == null || componentInstances.isEmpty()) {
1123 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1124 List<ComponentInstance> proxyInst = componentInstances.stream()
1125 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1126 .collect(Collectors.toList());
1127 if (proxyInst != null && !proxyInst.isEmpty()) {
1128 for (ComponentInstance inst : proxyInst) {
1129 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1133 if (serviceProxyInstanceList.isEmpty()) {
1136 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1137 .getLatestByName("serviceProxy");
1138 if (serviceProxyOrigin.isRight()) {
1139 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1140 serviceProxyOrigin.right().value());
1141 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1143 Component origComponent = serviceProxyOrigin.left().value();
1145 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1146 Component serviceComponent = null;
1147 ComponentParametersView componentParametersView = new ComponentParametersView();
1148 componentParametersView.disableAll();
1149 componentParametersView.setIgnoreCategories(false);
1150 componentParametersView.setIgnoreProperties(false);
1151 componentParametersView.setIgnoreInputs(false);
1152 componentParametersView.setIgnoreInterfaces(false);
1153 componentParametersView.setIgnoreRequirements(false);
1154 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1155 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1156 if (service.isRight()) {
1157 log.debug("Failed to fetch resource with id {} for instance {}",
1158 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1160 serviceComponent = service.left().value();
1163 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1164 entryProxy.getValue());
1165 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1168 return Either.left(nodeTypesMap);
1171 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1172 final Component container, final ToscaTemplate toscaNode) {
1173 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1175 if (CollectionUtils.isEmpty(componentInstances)) {
1178 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1179 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1180 .collect(Collectors.toList());
1181 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1182 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1183 final Map<String, ToscaNodeType> nodeTypes =
1184 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1185 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1191 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1192 Component proxyComponent, ComponentInstance componentInstance) {
1193 ToscaNodeType toscaNodeType = new ToscaNodeType();
1194 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1196 toscaNodeType.setDerived_from(derivedFrom);
1197 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1198 if (dataTypesEither.isRight()) {
1199 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1201 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1202 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1203 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1205 if (MapUtils.isNotEmpty(capabilities)) {
1206 toscaNodeType.setCapabilities(capabilities);
1208 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1209 .convertProxyRequirements(componentCache, componentInstance);
1210 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1211 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1213 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1214 proxyProperties.ifPresent(toscaNodeType::setProperties);
1216 Map<String, Object> interfaceMap = new HashMap<>();
1217 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1218 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1219 if (proxyInterfaces.isPresent()) {
1220 interfaceMap = proxyInterfaces.get();
1223 interfaceMap = interfacesOperationsConverter
1224 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1227 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1228 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1230 return toscaNodeType;
1233 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1234 ComponentInstance componentInstance,
1235 List<RequirementCapabilityRelDef> relations,
1236 ToscaNodeTemplate nodeTypeTemplate,
1237 Component originComponent,
1238 Map<String, Component> componentCache) {
1240 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements;
1241 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1243 if (isNotEmpty(requirementDefinitionList)) {
1245 toscaRequirements = buildRequirements(component, componentInstance,
1246 requirementDefinitionList, originComponent, componentCache);
1247 if (!toscaRequirements.isEmpty()) {
1248 nodeTypeTemplate.setRequirements(toscaRequirements);
1250 } catch (final Exception e) {
1251 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1252 componentInstance.getName(), e);
1253 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1256 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1257 return Either.left(nodeTypeTemplate);
1260 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1261 final ComponentInstance componentInstance,
1262 final List<RequirementCapabilityRelDef> filteredRelations,
1263 final Component originComponent,
1264 final Map<String, Component> componentCache)
1265 throws ToscaExportException {
1267 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1268 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1269 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1270 buildRequirement(componentInstance, originComponent, component.getComponentInstances(),
1271 relationshipDefinition, componentCache);
1272 toscaRequirements.add(toscaTemplateRequirementMap);
1275 return toscaRequirements;
1278 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1279 List<RequirementCapabilityRelDef> relations) {
1280 return relations.stream()
1281 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1284 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1285 final Component fromOriginComponent,
1286 final List<ComponentInstance> instancesList,
1287 final RequirementCapabilityRelDef relationshipDefinition,
1288 final Map<String, Component> componentCache)
1289 throws ToscaExportException {
1291 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1292 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1293 .getRelationships().get(0);
1294 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1296 final ComponentInstance toInstance = instancesList.stream()
1297 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1298 .findFirst().orElse(null);
1299 if (toInstance == null) {
1300 final String errorMsg = String
1301 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1302 relationshipDefinition.getToNode());
1303 log.debug(errorMsg);
1304 throw new ToscaExportException(errorMsg);
1306 final Optional<RequirementDefinition> reqOpt =
1307 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1308 if (reqOpt.isEmpty()) {
1309 final String errorMsg = String
1310 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1311 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1312 log.debug(errorMsg);
1313 throw new ToscaExportException(errorMsg);
1315 final ComponentParametersView filter = new ComponentParametersView(true);
1316 filter.setIgnoreComponentInstances(false);
1317 filter.setIgnoreCapabilities(false);
1318 filter.setIgnoreGroups(false);
1319 final Either<Component, StorageOperationStatus> getOriginRes =
1320 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1321 if (getOriginRes.isRight()) {
1322 final String errorMsg = String.format(
1323 "Failed to build substituted name for the requirement %s. "
1324 + "Failed to get an origin component with uniqueId %s",
1325 reqOpt.get().getName(), toInstance.getActualComponentUid());
1326 log.debug(errorMsg);
1327 throw new ToscaExportException(errorMsg);
1329 final Component toOriginComponent = getOriginRes.left().value();
1330 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1331 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1332 if (capOpt.isEmpty()) {
1333 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1334 if (capOpt.isEmpty()) {
1335 final String errorMsg = String
1336 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1337 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1338 log.debug(errorMsg);
1339 throw new ToscaExportException(errorMsg);
1342 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1343 capabilityRequirementRelationship, toInstance, componentCache);
1346 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1347 CapabilityDefinition capability) {
1348 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1349 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1352 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1353 Component toOriginComponent, Component fromOriginComponent,
1354 RequirementDefinition requirement) {
1355 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1356 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1357 if (!cap.isPresent()) {
1358 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1359 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1364 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1365 final Component toOriginComponent,
1366 final CapabilityDefinition capability,
1367 final RequirementDefinition requirement,
1368 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1369 final ComponentInstance toInstance,
1370 final Map<String, Component> componentCache)
1371 throws ToscaExportException {
1373 List<String> reducedPath = capability.getPath();
1374 if (capability.getOwnerId() != null) {
1375 reducedPath = capabilityRequirementConverter
1376 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1378 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1379 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1380 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1381 if (capabilityNameEither.isRight()) {
1382 final String errorMsg = String.format(
1383 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1384 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1387 throw new ToscaExportException(errorMsg);
1389 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1390 .buildSubstitutedName(componentCache, fromOriginComponent,
1391 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1392 if (requirementNameEither.isRight()) {
1393 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1394 + "with name %s on a component with uniqueId %s",
1395 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1396 log.debug(errorMsg);
1397 throw new ToscaExportException(errorMsg);
1399 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1400 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1401 toscaRequirement.setNode(toInstance.getName());
1402 toscaRequirement.setCapability(capabilityNameEither.left().value());
1403 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1404 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1406 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1410 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1411 Map<String, List<RequirementDefinition>> reqMap,
1412 RelationshipInfo reqAndRelationshipPair,
1413 String fromInstanceId) {
1414 for (List<RequirementDefinition> reqList : reqMap.values()) {
1415 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1416 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1418 if (reqOpt.isPresent()) {
1422 return Optional.empty();
1426 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1427 * 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
1428 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1430 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1431 RequirementDefinition requirement, String fromInstanceId) {
1432 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1433 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1434 reqAndRelationshipPair.getRequirement());
1437 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1441 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1442 Component originComponent) {
1443 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1444 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1445 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1448 private boolean isCvfc(Component component) {
1449 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1452 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1453 Map<String, Component> componentCache) {
1454 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1455 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1456 .convertSubstitutionMappingCapabilities(componentCache, component);
1457 if (toscaCapabilitiesRes.isRight()) {
1458 result = Either.right(toscaCapabilitiesRes.right().value());
1459 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1460 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1461 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1462 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1464 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1468 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1469 Map<String, DataTypeDefinition> dataTypes) {
1470 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1471 if (!toscaCapabilities.isEmpty()) {
1472 nodeType.setCapabilities(toscaCapabilities);
1474 log.debug("Finish convert Capabilities for node type");
1475 return Either.left(nodeType);
1478 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1479 if (artifacts == null) {
1482 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1483 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1484 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1485 artifact.setFile(entry.getValue().getFile());
1486 artifact.setType(entry.getValue().getType());
1487 arts.put(entry.getKey(), artifact);
1492 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1493 if (inNodeFilter == null) {
1496 NodeFilter nodeFilter = new NodeFilter();
1497 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1498 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1499 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1500 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1501 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1502 copyNodeFilterProperties(origProperties, propertiesCopy);
1503 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1504 nodeFilter.setCapabilities(capabilitiesCopy);
1506 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1507 nodeFilter.setProperties(propertiesCopy);
1509 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1510 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1514 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1515 if (substitutionFilterDataDefinition == null) {
1518 NodeFilter nodeFilter = new NodeFilter();
1519 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1520 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1521 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1522 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1523 nodeFilter.setProperties(propertiesCopy);
1525 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1526 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1529 private Object cloneToscaId(Object toscaId) {
1530 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1533 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1534 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1535 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1538 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1539 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1540 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1544 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1545 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1546 CapabilityFilter capabilityFilter = new CapabilityFilter();
1547 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1548 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1549 capabilityFilter.setProperties(propertiesCopy);
1550 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1551 capabilitiesCopy.add(capabilityFilterCopyMap);
1555 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1556 List<Map<String, List<Object>>> propertiesCopy) {
1557 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1560 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1561 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1562 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1563 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1564 String propertyName = propertyDataDefinition.getName();
1565 if (propertyMapCopy.containsKey(propertyName)) {
1566 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1568 if (propertyName != null) {
1569 List<Object> propsList = new ArrayList<>();
1570 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1571 propertyMapCopy.put(propertyName, propsList);
1573 propertyMapCopy.putAll(propertyValObj);
1578 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1581 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1582 final List<Map<String, List<Object>>> propertiesCopy) {
1583 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1586 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1587 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1588 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1589 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1590 final String propertyName = propertyDataDefinition.getName();
1591 if (propertyMapCopy.containsKey(propertyName)) {
1592 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1594 if (propertyName != null) {
1595 final List<Object> propsList = new ArrayList<>();
1596 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1597 propertyMapCopy.put(propertyName, propsList);
1599 propertyMapCopy.putAll(propertyValObj);
1604 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1607 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1608 if (propertyValObj.containsKey(propertyName)) {
1609 propsList.add(propertyValObj.get(propertyName));
1611 propsList.add(propertyValObj);
1615 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1616 Map<String, List<Object>> tempMap = new HashMap<>();
1617 tempMap.put(entry.getKey(), entry.getValue());
1618 propertiesCopy.add(tempMap);
1621 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1622 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1623 return Collections.emptyMap();
1625 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1626 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1629 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1630 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1631 return Collections.emptyMap();
1633 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1634 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1637 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1638 if (Objects.isNull(proxyComponent)) {
1639 return Optional.empty();
1641 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1642 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1643 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1644 proxyProperties.putAll(proxyComponent.getProperties().stream()
1645 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1646 .toMap(PropertyDataDefinition::getName,
1647 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1649 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1652 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1653 Map<String, ToscaProperty> mergedProperties) {
1654 if (CollectionUtils.isEmpty(componentInputs)) {
1657 for (InputDefinition input : componentInputs) {
1658 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1659 mergedProperties.put(input.getName(), property);
1663 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1664 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1665 return Optional.empty();
1667 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1668 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1670 // always available in the proxy node template
1671 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1673 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1676 private static class CustomRepresenter extends Representer {
1678 CustomRepresenter() {
1680 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1681 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1682 // null representer is exceptional and it is stored as an instance
1685 this.nullRepresenter = new RepresentNull();
1688 public boolean validateGetInputValue(final Object valueObj) {
1689 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1692 if (valueObj instanceof List) {
1693 return ((List) valueObj).size() > 1;
1698 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1699 if (valueObj instanceof List) {
1700 return ((List) valueObj).size() > 1;
1706 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1707 if (propertyValue == null) {
1710 // skip not relevant for Tosca property
1711 if ("dependencies".equals(property.getName())) {
1714 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1717 removeDefaultP(propertyValue);
1718 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1719 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1720 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1722 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1725 private void removeDefaultP(final Object propertyValue) {
1726 if (propertyValue instanceof Map) {
1727 final Map mapPropertyValue = ((Map) propertyValue);
1728 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1729 Object defaultValue = null;
1730 while (iter.hasNext()) {
1731 final Map.Entry entry = iter.next();
1732 if ("_defaultp_".equals(entry.getKey())) {
1733 defaultValue = entry.getValue();
1735 } else if (entry.getValue() instanceof Map) {
1736 removeDefaultP(entry.getValue());
1739 if (defaultValue != null) {
1740 mapPropertyValue.putIfAbsent("default", defaultValue);
1746 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1747 // remove the bean type from the output yaml (!! ...)
1748 if (!classTags.containsKey(javaBean.getClass())) {
1749 addClassTag(javaBean.getClass(), Tag.MAP);
1751 return super.representJavaBean(properties, javaBean);
1754 private class RepresentToscaAttribute implements Represent {
1757 public Node representData(Object data) {
1758 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1759 return represent(toscaAttribute.asToscaMap());
1763 private class RepresentToscaPropertyAssignment implements Represent {
1765 public Node representData(Object data) {
1766 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1767 if (toscaOperationAssignment.getValue() instanceof String) {
1768 final String stringValue = (String) toscaOperationAssignment.getValue();
1769 if (isPropertyOrAttributeFunction(stringValue)) {
1770 return representGetAttribute(stringValue);
1772 return representScalar(Tag.STR, stringValue);
1774 return represent(null);
1777 public Node representGetAttribute(final String getAttributeFunction) {
1778 return represent(new Yaml().load(getAttributeFunction));
1781 public boolean isPropertyOrAttributeFunction(final String value) {
1783 final Yaml yaml = new Yaml();
1784 final Object yamlObj = yaml.load(value);
1785 if (!(yamlObj instanceof Map)) {
1788 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1789 if (getAttributeMap.size() != 1) {
1792 final List<String> functionList = Arrays
1793 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1794 final Optional<String> function = getAttributeMap.keySet().stream()
1795 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1796 if (function.isEmpty()) {
1799 final String functionName = function.get();
1800 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1801 if (GET_INPUT.getFunctionName().equals(functionName)) {
1802 return validateGetInputValue(getAttributeValueObj);
1804 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1806 } catch (final Exception ignored) {
1812 private class RepresentNull implements Represent {
1815 public Node representData(Object data) {
1816 // possible values are here http://yaml.org/type/null.html
1817 return representScalar(Tag.NULL, "");
1822 private static class UnsortedPropertyUtils extends PropertyUtils {
1825 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1826 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1827 return new LinkedHashSet<>(fields);
1831 private Configuration getConfiguration() {
1832 return ConfigurationManager.getConfigurationManager().getConfiguration();