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.lang3.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());
475 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), resource.getModel());
478 Service service = (Service) component;
479 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
480 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
481 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
482 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
483 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
484 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
485 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
488 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
489 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
490 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
494 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
496 for (final String key : component.getCategorySpecificMetadata().keySet()) {
497 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
498 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
501 return toscaMetadata;
504 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
505 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
506 return INVARIANT_UUID;
508 return jsonPresentationField.getPresentation();
511 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
512 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
513 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
514 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
515 return Either.right(ToscaError.GENERAL_ERROR);
517 Map<String, Component> componentCache = new HashMap<>();
518 if (!ModelConverter.isAtomicComponent(component)) {
519 final List<Map<String, Map<String, String>>> additionalImports =
520 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
521 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
522 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
523 if (isNotEmpty(toscaArtifacts)) {
524 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
525 if (artifactDefinition != null) {
526 Map<String, Map<String, String>> importsListMember = new HashMap<>();
527 Map<String, String> interfaceFiles = new HashMap<>();
528 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
529 StringBuilder keyNameBuilder = new StringBuilder();
530 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
531 .append("-interface");
532 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
533 additionalImports.add(importsListMember);
536 List<ComponentInstance> componentInstances = component.getComponentInstances();
537 if (componentInstances != null && !componentInstances.isEmpty()) {
538 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
540 toscaTemplate.setDependencies(dependencies);
541 toscaTemplate.setImports(additionalImports);
543 log.debug("currently imports supported for VF and service only");
545 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
548 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
549 return getConfiguration().getDefaultImports();
552 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
553 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
554 log.debug("createDependency componentCache {}", componentCache);
555 Component componentRI = componentCache.get(componentInstance.getComponentUid());
556 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
557 // all resource must be only once!
558 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
559 if ((resource.isRight()) && (log.isDebugEnabled())) {
560 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
561 componentInstance.getUniqueId());
564 final Component fetchedComponent = resource.left().value();
565 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
566 addDependencies(imports, dependencies, componentRI);
571 * Sets a componentCache from the given component/resource.
573 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
574 final Component fetchedComponent) {
575 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
576 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
577 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
578 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
579 .getToscaFullElement(componentInstance.getSourceModelUid());
580 if (sourceService.isRight() && (log.isDebugEnabled())) {
581 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
582 componentInstance.getUniqueId());
584 final Component fetchedSource = sourceService.left().value();
585 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
586 return fetchedSource;
588 return fetchedComponent;
592 * Retrieves all derived_from nodes and stores it in a predictable order.
594 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
595 final Component fetchedComponent) {
596 final Set<Component> componentsList = new LinkedHashSet<>();
597 if (fetchedComponent instanceof Resource) {
598 log.debug("fetchedComponent is a resource {}", fetchedComponent);
599 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
600 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
601 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
602 log.debug("Started entry.getValue() : {}", entry.getValue());
603 if (!NATIVE_ROOT.equals(entry.getValue())) {
604 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
605 if (resourcefetched != null && resourcefetched.isLeft()) {
606 componentsList.add(resourcefetched.left().value());
610 setImports(imports, dependencies, componentsList);
612 setImports(imports, dependencies, fetchedComponent);
618 * Returns all derived_from nodes found.
620 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
621 final Resource parentResource = (Resource) fetchedComponent;
622 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
623 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
624 componentsList.add(fetchedComponent);
625 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
626 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
627 .getToscaElement(componentInstance.getComponentUid());
628 if (resourcefetched != null && resourcefetched.isLeft()) {
629 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
630 if (MapUtils.isNotEmpty(derivedWithId)) {
631 derivedFromMapOfIdToName.putAll(derivedWithId);
636 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
638 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
639 return Optional.ofNullable(derivedFromMapOfIdToName);
643 * Creates a resource map and adds it to the import list.
645 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
646 final Set<Component> componentsList) {
647 componentsList.forEach(component -> setImports(imports, dependencies, component));
650 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
651 final Component component) {
652 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
653 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
654 if (artifactDefinition != null) {
655 final Map<String, String> files = new HashMap<>();
656 final String artifactName = artifactDefinition.getArtifactName();
657 files.put(IMPORTS_FILE_KEY, artifactName);
658 final StringBuilder keyNameBuilder = new StringBuilder();
659 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
660 keyNameBuilder.append("-");
661 keyNameBuilder.append(component.getName());
662 addImports(imports, keyNameBuilder, files);
663 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
664 if (!ModelConverter.isAtomicComponent(component)) {
665 final Map<String, String> interfaceFiles = new HashMap<>();
666 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
667 keyNameBuilder.append("-interface");
668 addImports(imports, keyNameBuilder, interfaceFiles);
674 * Adds the found resource to the import definition list.
676 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
677 final Map<String, String> files) {
678 final String mapKey = keyNameBuilder.toString();
679 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
680 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
681 importsListMember.put(keyNameBuilder.toString(), files);
682 imports.add(importsListMember);
686 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
687 Map<String, ToscaNodeType> nodeTypes) {
688 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
691 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
692 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
693 boolean isAssociatedComponent) {
694 log.debug("start convert node type for {}", component.getUniqueId());
695 ToscaNodeType toscaNodeType = createNodeType(component);
696 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
697 .getAllInterfaceLifecycleTypes();
698 if (lifecycleTypeEither.isRight()) {
699 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
700 return Either.right(ToscaError.GENERAL_ERROR);
702 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
703 .collect(Collectors.toList());
704 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
705 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
706 if (dataTypesEither.isRight()) {
707 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
708 return Either.right(ToscaError.GENERAL_ERROR);
710 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
711 List<InputDefinition> inputDef = component.getInputs();
712 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
713 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
714 addInputsToProperties(dataTypes, inputDef, mergedProperties);
715 final Map<String, ToscaAttribute> toscaAttributeMap;
716 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
717 if (!toscaAttributeMap.isEmpty()) {
718 toscaNodeType.setAttributes(toscaAttributeMap);
720 if (CollectionUtils.isNotEmpty(component.getProperties())) {
721 List<PropertyDefinition> properties = component.getProperties();
722 Map<String, ToscaProperty> convertedProperties = properties.stream()
723 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
724 .toMap(PropertyDataDefinition::getName,
725 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
726 // merge component properties and inputs properties
727 mergedProperties.putAll(convertedProperties);
729 if (MapUtils.isNotEmpty(mergedProperties)) {
730 toscaNodeType.setProperties(mergedProperties);
732 /* convert private data_types */
733 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
734 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
735 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
736 for (DataTypeDefinition dataType : privateDataTypes) {
737 log.debug("Emitting private data type: component.name={} dataType.name={}",
738 component.getNormalizedName(), dataType.getName());
739 ToscaDataType toscaDataType = new ToscaDataType();
740 toscaDataType.setDerived_from(dataType.getDerivedFromName());
741 toscaDataType.setDescription(dataType.getDescription());
742 toscaDataType.setVersion(dataType.getVersion());
743 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
744 toscaDataType.setProperties(dataType.getProperties().stream()
745 .collect(Collectors.toMap(
746 PropertyDataDefinition::getName,
747 s -> propertyConvertor
748 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
751 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
753 toscaNode.setData_types(toscaDataTypeMap);
756 // Extracted to method for code reuse
757 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
760 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
761 final Map<String, DataTypeDefinition> dataTypes) {
762 if (CollectionUtils.isEmpty(attributeList)) {
763 return Collections.emptyMap();
765 final AttributeConverter converter = new AttributeConverter(dataTypes);
766 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
767 for (final AttributeDefinition attributeDefinition : attributeList) {
768 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
770 return toscaAttributeMap;
773 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
774 Component component, ToscaTemplate toscaNode,
775 Map<String, ToscaNodeType> nodeTypes,
776 ToscaNodeType toscaNodeType,
777 Map<String, DataTypeDefinition> dataTypes) {
778 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
780 if (capabilities.isRight()) {
781 return Either.right(capabilities.right().value());
783 toscaNodeType = capabilities.left().value();
784 log.debug("Capabilities converted for {}", component.getUniqueId());
786 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
787 .convertRequirements(componentsCache, component, toscaNodeType);
788 if (requirements.isRight()) {
789 return Either.right(requirements.right().value());
791 toscaNodeType = requirements.left().value();
792 log.debug("Requirements converted for {}", component.getUniqueId());
794 String toscaResourceName;
795 switch (component.getComponentType()) {
797 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
798 .getMetadataDataDefinition()).getToscaResourceName();
801 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
802 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
805 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
806 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
809 nodeTypes.put(toscaResourceName, toscaNodeType);
810 toscaNode.setNode_types(nodeTypes);
811 log.debug("finish convert node type for {}", component.getUniqueId());
812 return Either.left(toscaNode);
815 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
816 final Map<String, Component> componentCache,
817 final Map<String, DataTypeDefinition> dataTypes,
818 final ToscaTopolgyTemplate topologyTemplate) {
820 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
821 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
822 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
823 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
824 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
826 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
827 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
828 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
830 Map<String, ToscaGroupTemplate> groupsMap = null;
831 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
832 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
833 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
834 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
836 nodeTemplate.setType(componentInstance.getToscaComponentName());
837 nodeTemplate.setDirectives(componentInstance.getDirectives());
838 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
840 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
841 .getOriginComponent(componentCache, componentInstance);
842 if (originComponentRes.isRight()) {
843 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
846 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
847 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
848 if (requirements.isRight()) {
849 convertNodeTemplatesRes = Either.right(requirements.right().value());
852 final String instanceUniqueId = componentInstance.getUniqueId();
853 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
855 nodeTemplate = requirements.left().value();
857 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
859 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
860 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
861 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
863 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
866 final Either<ToscaNodeTemplate, ToscaError> capabilities =
867 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
868 if (capabilities.isRight()) {
869 convertNodeTemplatesRes = Either.right(capabilities.right().value());
872 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
874 nodeTemplate = capabilities.left().value();
875 final Map<String, Object> props = new HashMap<>();
876 final Map<String, Object> attribs = new HashMap<>();
878 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
879 // Adds the properties of parent component to map
880 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
881 addAttributesOfParentComponent(originalComponent, attribs);
884 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
885 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
887 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
888 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
891 if (componentInstancesInputs != null
892 && componentInstancesInputs.containsKey(instanceUniqueId)
893 && !isComponentOfTypeServiceProxy(componentInstance)) {
894 //For service proxy the inputs are already handled under instance properties above
895 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
898 //M3[00001] - NODE TEMPLATE INTERFACES - START
899 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
900 //M3[00001] - NODE TEMPLATE INTERFACES - END
901 if (MapUtils.isNotEmpty(props)) {
902 nodeTemplate.setProperties(props);
904 if (MapUtils.isNotEmpty(attribs)) {
905 nodeTemplate.setAttributes(attribs);
908 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
909 if (CollectionUtils.isNotEmpty(groupInstances)) {
910 if (groupsMap == null) {
911 groupsMap = new HashMap<>();
913 for (final GroupInstance groupInst : groupInstances) {
914 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
915 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
920 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
922 if (groupsMap != null) {
923 log.debug("instance groups added");
924 topologyTemplate.addGroups(groupsMap);
926 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
927 ((Service) component).getForwardingPaths())) {
928 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
929 ForwardingPathToscaUtil
930 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
931 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
933 if (convertNodeTemplatesRes == null) {
934 convertNodeTemplatesRes = Either.left(nodeTemplates);
936 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
937 return convertNodeTemplatesRes;
940 private void handleInstanceInterfaces(
941 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
942 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
943 String instanceUniqueId,
944 Component parentComponent) {
946 if (MapUtils.isEmpty(componentInstanceInterfaces)
947 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
948 nodeTemplate.setInterfaces(null);
952 final List<ComponentInstanceInterface> currServiceInterfaces =
953 componentInstanceInterfaces.get(instanceUniqueId);
955 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
956 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
957 .getUniqueId(), instInterface));
959 final Map<String, Object> interfaceMap = interfacesOperationsConverter
960 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
961 isComponentOfTypeServiceProxy(componentInstance));
963 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
964 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
967 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
968 return Objects.nonNull(componentInstance.getOriginType())
969 && componentInstance.getOriginType().getValue().equals("Service Proxy");
972 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
973 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
974 String instanceUniqueId, Map<String, Object> props) {
976 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
977 if (instanceInputsList != null) {
978 instanceInputsList.forEach(input -> {
979 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
980 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
985 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
986 final Map<String, DataTypeDefinition> dataTypes,
987 final String instanceUniqueId,
988 final Map<String, Object> props) {
990 if (isNotEmpty(componentInstancesProperties)) {
991 componentInstancesProperties.get(instanceUniqueId)
992 // Converts and adds each value to property map
993 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
997 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
998 final String instanceUniqueId,
999 final Map<String, Object> attribs) {
1001 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1002 componentInstancesAttributes.get(instanceUniqueId).stream()
1003 // Filters out Attributes with empty default values
1004 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1005 // Converts and adds each value to attribute map
1006 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1010 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1011 Component componentOfInstance, Map<String, Object> props) {
1013 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1014 if (isNotEmpty(componentProperties)) {
1015 componentProperties.stream()
1016 // Filters out properties with empty default values
1017 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1018 // Converts and adds each value to property map
1019 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1023 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1025 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1026 if (isNotEmpty(componentAttributes)) {
1027 componentAttributes.stream()
1028 // Filters out Attributes with empty default values
1029 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1030 // Converts and adds each value to attribute map
1031 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1035 private ToscaNodeType createNodeType(Component component) {
1036 ToscaNodeType toscaNodeType = new ToscaNodeType();
1037 if (ModelConverter.isAtomicComponent(component)) {
1038 if (((Resource) component).getDerivedFrom() != null) {
1039 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1041 toscaNodeType.setDescription(component.getDescription());
1043 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1045 toscaNodeType.setDerived_from(derivedFrom);
1047 return toscaNodeType;
1050 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1052 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1053 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1054 List<ComponentInstance> componentInstances = container.getComponentInstances();
1055 if (CollectionUtils.isEmpty(componentInstances)) {
1058 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1059 componentInstances.stream()
1060 .filter(this::isComponentOfTypeServiceProxy)
1061 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1062 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1065 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1066 Component serviceComponent;
1067 ComponentParametersView componentParametersView = new ComponentParametersView();
1068 componentParametersView.disableAll();
1069 componentParametersView.setIgnoreInterfaces(false);
1070 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1071 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1072 if (service.isRight()) {
1073 log.debug("Failed to fetch original service component with id {} for instance {}",
1074 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1075 return Either.right(ToscaError.GENERAL_ERROR);
1077 serviceComponent = service.left().value();
1080 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1081 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
1082 if (lifecycleTypeEither.isRight()) {
1083 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1084 return Either.right(ToscaError.GENERAL_ERROR);
1087 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1088 .map(InterfaceDataDefinition::getType)
1089 .collect(Collectors.toList());
1090 //Add interface types for local interfaces in the original service component for proxy
1091 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1092 allGlobalInterfaceTypes);
1093 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1094 proxyInterfaceTypes.putAll(localInterfaceTypes);
1098 return Either.left(proxyInterfaceTypes);
1101 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1102 Component container) {
1104 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1105 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1107 List<ComponentInstance> componentInstances = container.getComponentInstances();
1109 if (componentInstances == null || componentInstances.isEmpty()) {
1112 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1113 List<ComponentInstance> proxyInst = componentInstances.stream()
1114 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1115 .collect(Collectors.toList());
1116 if (proxyInst != null && !proxyInst.isEmpty()) {
1117 for (ComponentInstance inst : proxyInst) {
1118 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1122 if (serviceProxyInstanceList.isEmpty()) {
1125 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1126 .getLatestByName("serviceProxy", null);
1127 if (serviceProxyOrigin.isRight()) {
1128 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1129 serviceProxyOrigin.right().value());
1130 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1132 Component origComponent = serviceProxyOrigin.left().value();
1134 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1135 Component serviceComponent = null;
1136 ComponentParametersView componentParametersView = new ComponentParametersView();
1137 componentParametersView.disableAll();
1138 componentParametersView.setIgnoreCategories(false);
1139 componentParametersView.setIgnoreProperties(false);
1140 componentParametersView.setIgnoreInputs(false);
1141 componentParametersView.setIgnoreInterfaces(false);
1142 componentParametersView.setIgnoreRequirements(false);
1143 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1144 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1145 if (service.isRight()) {
1146 log.debug("Failed to fetch resource with id {} for instance {}",
1147 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1149 serviceComponent = service.left().value();
1152 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1153 entryProxy.getValue());
1154 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1157 return Either.left(nodeTypesMap);
1160 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1161 final Component container, final ToscaTemplate toscaNode) {
1162 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1164 if (CollectionUtils.isEmpty(componentInstances)) {
1167 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1168 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1169 .collect(Collectors.toList());
1170 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1171 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1172 final Map<String, ToscaNodeType> nodeTypes =
1173 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1174 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1180 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1181 Component proxyComponent, ComponentInstance componentInstance) {
1182 ToscaNodeType toscaNodeType = new ToscaNodeType();
1183 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1185 toscaNodeType.setDerived_from(derivedFrom);
1186 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1187 if (dataTypesEither.isRight()) {
1188 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1190 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1191 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1192 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1194 if (MapUtils.isNotEmpty(capabilities)) {
1195 toscaNodeType.setCapabilities(capabilities);
1197 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1198 .convertProxyRequirements(componentCache, componentInstance);
1199 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1200 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1202 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1203 proxyProperties.ifPresent(toscaNodeType::setProperties);
1205 Map<String, Object> interfaceMap = new HashMap<>();
1206 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1207 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1208 if (proxyInterfaces.isPresent()) {
1209 interfaceMap = proxyInterfaces.get();
1212 interfaceMap = interfacesOperationsConverter
1213 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1216 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1217 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1219 return toscaNodeType;
1222 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1223 ComponentInstance componentInstance,
1224 List<RequirementCapabilityRelDef> relations,
1225 ToscaNodeTemplate nodeTypeTemplate,
1226 Component originComponent,
1227 Map<String, Component> componentCache) {
1229 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1231 if (isNotEmpty(requirementDefinitionList)) {
1233 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1234 if (!toscaRequirements.isEmpty()) {
1235 nodeTypeTemplate.setRequirements(toscaRequirements);
1237 } catch (final Exception e) {
1238 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1239 componentInstance.getName(), e);
1240 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1243 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1244 return Either.left(nodeTypeTemplate);
1247 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1248 final ComponentInstance componentInstance,
1249 final List<RequirementCapabilityRelDef> filteredRelations,
1250 final Component originComponent,
1251 final Map<String, Component> componentCache)
1252 throws ToscaExportException {
1254 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1255 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1256 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1257 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1258 toscaRequirements.add(toscaTemplateRequirementMap);
1261 return toscaRequirements;
1264 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1265 List<RequirementCapabilityRelDef> relations) {
1266 return relations.stream()
1267 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1270 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1271 final Component fromOriginComponent,
1272 final List<ComponentInstance> instancesList,
1273 final RequirementCapabilityRelDef relationshipDefinition,
1274 final Map<String, Component> componentCache)
1275 throws ToscaExportException {
1277 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1278 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1279 .getRelationships().get(0);
1280 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1282 final ComponentInstance toInstance = instancesList.stream()
1283 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1284 .findFirst().orElse(null);
1285 if (toInstance == null) {
1286 final String errorMsg = String
1287 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1288 relationshipDefinition.getToNode());
1289 log.debug(errorMsg);
1290 throw new ToscaExportException(errorMsg);
1292 final Optional<RequirementDefinition> reqOpt =
1293 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1294 if (reqOpt.isEmpty()) {
1295 final String errorMsg = String
1296 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1297 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1298 log.debug(errorMsg);
1299 throw new ToscaExportException(errorMsg);
1301 final ComponentParametersView filter = new ComponentParametersView(true);
1302 filter.setIgnoreComponentInstances(false);
1303 filter.setIgnoreCapabilities(false);
1304 filter.setIgnoreGroups(false);
1305 final Either<Component, StorageOperationStatus> getOriginRes =
1306 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1307 if (getOriginRes.isRight()) {
1308 final String errorMsg = String.format(
1309 "Failed to build substituted name for the requirement %s. "
1310 + "Failed to get an origin component with uniqueId %s",
1311 reqOpt.get().getName(), toInstance.getActualComponentUid());
1312 log.debug(errorMsg);
1313 throw new ToscaExportException(errorMsg);
1315 final Component toOriginComponent = getOriginRes.left().value();
1316 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1317 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1318 if (capOpt.isEmpty()) {
1319 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1320 if (capOpt.isEmpty()) {
1321 final String errorMsg = String
1322 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1323 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1324 log.debug(errorMsg);
1325 throw new ToscaExportException(errorMsg);
1328 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1329 capabilityRequirementRelationship, toInstance, componentCache);
1332 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1333 CapabilityDefinition capability) {
1334 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1335 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1338 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1339 Component toOriginComponent, Component fromOriginComponent,
1340 RequirementDefinition requirement) {
1341 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1342 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1343 if (!cap.isPresent()) {
1344 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1345 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1350 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1351 final Component toOriginComponent,
1352 final CapabilityDefinition capability,
1353 final RequirementDefinition requirement,
1354 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1355 final ComponentInstance toInstance,
1356 final Map<String, Component> componentCache)
1357 throws ToscaExportException {
1359 List<String> reducedPath = capability.getPath();
1360 if (capability.getOwnerId() != null) {
1361 reducedPath = capabilityRequirementConverter
1362 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1364 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1365 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1366 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1367 if (capabilityNameEither.isRight()) {
1368 final String errorMsg = String.format(
1369 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1370 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1373 throw new ToscaExportException(errorMsg);
1375 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1376 .buildSubstitutedName(componentCache, fromOriginComponent,
1377 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1378 if (requirementNameEither.isRight()) {
1379 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1380 + "with name %s on a component with uniqueId %s",
1381 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1382 log.debug(errorMsg);
1383 throw new ToscaExportException(errorMsg);
1385 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1386 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1387 toscaRequirement.setNode(toInstance.getName());
1388 toscaRequirement.setCapability(capabilityNameEither.left().value());
1389 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1390 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1392 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1396 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1397 Map<String, List<RequirementDefinition>> reqMap,
1398 RelationshipInfo reqAndRelationshipPair,
1399 String fromInstanceId) {
1400 for (List<RequirementDefinition> reqList : reqMap.values()) {
1401 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1402 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1404 if (reqOpt.isPresent()) {
1408 return Optional.empty();
1412 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1413 * 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
1414 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1416 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1417 RequirementDefinition requirement, String fromInstanceId) {
1418 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1419 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1420 reqAndRelationshipPair.getRequirement());
1423 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1427 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1428 Component originComponent) {
1429 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1430 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1431 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1434 private boolean isCvfc(Component component) {
1435 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1438 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1439 Map<String, Component> componentCache) {
1440 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1441 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1442 .convertSubstitutionMappingCapabilities(componentCache, component);
1443 if (toscaCapabilitiesRes.isRight()) {
1444 result = Either.right(toscaCapabilitiesRes.right().value());
1445 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1446 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1447 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1448 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1450 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1454 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1455 Map<String, DataTypeDefinition> dataTypes) {
1456 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1457 if (!toscaCapabilities.isEmpty()) {
1458 nodeType.setCapabilities(toscaCapabilities);
1460 log.debug("Finish convert Capabilities for node type");
1461 return Either.left(nodeType);
1464 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1465 if (artifacts == null) {
1468 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1469 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1470 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1471 artifact.setFile(entry.getValue().getFile());
1472 artifact.setType(entry.getValue().getType());
1473 arts.put(entry.getKey(), artifact);
1478 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1479 if (inNodeFilter == null) {
1482 NodeFilter nodeFilter = new NodeFilter();
1483 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1484 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1485 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1486 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1487 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1488 copyNodeFilterProperties(origProperties, propertiesCopy);
1489 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1490 nodeFilter.setCapabilities(capabilitiesCopy);
1492 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1493 nodeFilter.setProperties(propertiesCopy);
1495 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1496 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1500 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1501 if (substitutionFilterDataDefinition == null) {
1504 NodeFilter nodeFilter = new NodeFilter();
1505 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1506 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1507 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1508 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1509 nodeFilter.setProperties(propertiesCopy);
1511 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1512 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1515 private Object cloneToscaId(Object toscaId) {
1516 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1519 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1520 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1521 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1524 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1525 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1526 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1530 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1531 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1532 CapabilityFilter capabilityFilter = new CapabilityFilter();
1533 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1534 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1535 capabilityFilter.setProperties(propertiesCopy);
1536 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1537 capabilitiesCopy.add(capabilityFilterCopyMap);
1541 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1542 List<Map<String, List<Object>>> propertiesCopy) {
1543 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1546 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1547 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1548 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1549 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1550 String propertyName = propertyDataDefinition.getName();
1551 if (propertyMapCopy.containsKey(propertyName)) {
1552 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1554 if (propertyName != null) {
1555 List<Object> propsList = new ArrayList<>();
1556 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1557 propertyMapCopy.put(propertyName, propsList);
1559 propertyMapCopy.putAll(propertyValObj);
1564 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1567 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1568 final List<Map<String, List<Object>>> propertiesCopy) {
1569 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1572 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1573 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1574 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1575 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1576 final String propertyName = propertyDataDefinition.getName();
1577 if (propertyMapCopy.containsKey(propertyName)) {
1578 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1580 if (propertyName != null) {
1581 final List<Object> propsList = new ArrayList<>();
1582 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1583 propertyMapCopy.put(propertyName, propsList);
1585 propertyMapCopy.putAll(propertyValObj);
1590 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1593 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1594 if (propertyValObj.containsKey(propertyName)) {
1595 propsList.add(propertyValObj.get(propertyName));
1597 propsList.add(propertyValObj);
1601 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1602 Map<String, List<Object>> tempMap = new HashMap<>();
1603 tempMap.put(entry.getKey(), entry.getValue());
1604 propertiesCopy.add(tempMap);
1607 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1608 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1609 return Collections.emptyMap();
1611 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1612 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1615 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1616 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1617 return Collections.emptyMap();
1619 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1620 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1623 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1624 if (Objects.isNull(proxyComponent)) {
1625 return Optional.empty();
1627 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1628 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1629 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1630 proxyProperties.putAll(proxyComponent.getProperties().stream()
1631 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1632 .toMap(PropertyDataDefinition::getName,
1633 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1635 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1638 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1639 Map<String, ToscaProperty> mergedProperties) {
1640 if (CollectionUtils.isEmpty(componentInputs)) {
1643 for (InputDefinition input : componentInputs) {
1644 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1645 mergedProperties.put(input.getName(), property);
1649 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1650 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1651 return Optional.empty();
1653 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1654 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1656 // always available in the proxy node template
1657 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1659 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1662 private static class CustomRepresenter extends Representer {
1664 CustomRepresenter() {
1666 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1667 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1668 // null representer is exceptional and it is stored as an instance
1671 this.nullRepresenter = new RepresentNull();
1674 public boolean validateGetInputValue(final Object valueObj) {
1675 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1678 if (valueObj instanceof List) {
1679 return ((List) valueObj).size() > 1;
1684 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1685 if (valueObj instanceof List) {
1686 return ((List) valueObj).size() > 1;
1692 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1693 if (propertyValue == null) {
1696 // skip not relevant for Tosca property
1697 if ("dependencies".equals(property.getName())) {
1700 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1703 removeDefaultP(propertyValue);
1704 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1705 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1706 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1708 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1711 private void removeDefaultP(final Object propertyValue) {
1712 if (propertyValue instanceof Map) {
1713 final Map mapPropertyValue = ((Map) propertyValue);
1714 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1715 Object defaultValue = null;
1716 while (iter.hasNext()) {
1717 final Map.Entry entry = iter.next();
1718 if ("_defaultp_".equals(entry.getKey())) {
1719 defaultValue = entry.getValue();
1721 } else if (entry.getValue() instanceof Map) {
1722 removeDefaultP(entry.getValue());
1725 if (defaultValue != null) {
1726 mapPropertyValue.putIfAbsent("default", defaultValue);
1732 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1733 // remove the bean type from the output yaml (!! ...)
1734 if (!classTags.containsKey(javaBean.getClass())) {
1735 addClassTag(javaBean.getClass(), Tag.MAP);
1737 return super.representJavaBean(properties, javaBean);
1740 private class RepresentToscaAttribute implements Represent {
1743 public Node representData(Object data) {
1744 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1745 return represent(toscaAttribute.asToscaMap());
1749 private class RepresentToscaPropertyAssignment implements Represent {
1751 public Node representData(Object data) {
1752 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1753 if (toscaOperationAssignment.getValue() instanceof String) {
1754 final String stringValue = (String) toscaOperationAssignment.getValue();
1755 if (isPropertyOrAttributeFunction(stringValue)) {
1756 return representGetAttribute(stringValue);
1758 return representScalar(Tag.STR, stringValue);
1760 return represent(null);
1763 public Node representGetAttribute(final String getAttributeFunction) {
1764 return represent(new Yaml().load(getAttributeFunction));
1767 public boolean isPropertyOrAttributeFunction(final String value) {
1769 final Yaml yaml = new Yaml();
1770 final Object yamlObj = yaml.load(value);
1771 if (!(yamlObj instanceof Map)) {
1774 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1775 if (getAttributeMap.size() != 1) {
1778 final List<String> functionList = Arrays
1779 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1780 final Optional<String> function = getAttributeMap.keySet().stream()
1781 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1782 if (function.isEmpty()) {
1785 final String functionName = function.get();
1786 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1787 if (GET_INPUT.getFunctionName().equals(functionName)) {
1788 return validateGetInputValue(getAttributeValueObj);
1790 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1792 } catch (final Exception ignored) {
1798 private class RepresentNull implements Represent {
1801 public Node representData(Object data) {
1802 // possible values are here http://yaml.org/type/null.html
1803 return representScalar(Tag.NULL, "");
1808 private static class UnsortedPropertyUtils extends PropertyUtils {
1811 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1812 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1813 return new LinkedHashSet<>(fields);
1817 private Configuration getConfiguration() {
1818 return ConfigurationManager.getConfigurationManager().getConfiguration();