2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.tosca;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.collections.MapUtils.isNotEmpty;
24 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
25 import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
28 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
30 import fj.data.Either;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.LinkedHashMap;
38 import java.util.LinkedHashSet;
39 import java.util.List;
41 import java.util.Map.Entry;
42 import java.util.Objects;
43 import java.util.Optional;
45 import java.util.function.Supplier;
46 import java.util.stream.Collectors;
47 import lombok.NoArgsConstructor;
48 import org.apache.commons.collections.CollectionUtils;
49 import org.apache.commons.collections.MapUtils;
50 import org.apache.commons.lang.StringUtils;
51 import org.apache.commons.lang3.tuple.ImmutablePair;
52 import org.apache.commons.lang3.tuple.ImmutableTriple;
53 import org.apache.commons.lang3.tuple.Triple;
54 import org.onap.sdc.tosca.services.YamlUtil;
55 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
56 import org.openecomp.sdc.be.config.ConfigurationManager;
57 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
58 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
59 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
60 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
69 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
70 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
71 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
73 import org.openecomp.sdc.be.exception.ToscaExportException;
74 import org.openecomp.sdc.be.model.ArtifactDefinition;
75 import org.openecomp.sdc.be.model.AttributeDefinition;
76 import org.openecomp.sdc.be.model.CapabilityDefinition;
77 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
78 import org.openecomp.sdc.be.model.Component;
79 import org.openecomp.sdc.be.model.ComponentInstance;
80 import org.openecomp.sdc.be.model.ComponentInstanceInput;
81 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
82 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
83 import org.openecomp.sdc.be.model.ComponentParametersView;
84 import org.openecomp.sdc.be.model.DataTypeDefinition;
85 import org.openecomp.sdc.be.model.GroupInstance;
86 import org.openecomp.sdc.be.model.InputDefinition;
87 import org.openecomp.sdc.be.model.InterfaceDefinition;
88 import org.openecomp.sdc.be.model.PropertyDefinition;
89 import org.openecomp.sdc.be.model.RelationshipInfo;
90 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
91 import org.openecomp.sdc.be.model.RequirementDefinition;
92 import org.openecomp.sdc.be.model.Resource;
93 import org.openecomp.sdc.be.model.Service;
94 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
95 import org.openecomp.sdc.be.model.category.CategoryDefinition;
96 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
97 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
98 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
99 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
100 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
101 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
102 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
103 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
104 import org.openecomp.sdc.be.tosca.model.NodeFilter;
105 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
106 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
107 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
108 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
109 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
110 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
111 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
112 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
113 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
114 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
115 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
116 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
117 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
118 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
119 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
120 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
121 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
122 import org.openecomp.sdc.be.tosca.utils.InputConverter;
123 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
124 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
125 import org.openecomp.sdc.common.log.wrappers.Logger;
126 import org.springframework.beans.factory.annotation.Autowired;
127 import org.yaml.snakeyaml.DumperOptions;
128 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
129 import org.yaml.snakeyaml.Yaml;
130 import org.yaml.snakeyaml.introspector.BeanAccess;
131 import org.yaml.snakeyaml.introspector.Property;
132 import org.yaml.snakeyaml.introspector.PropertyUtils;
133 import org.yaml.snakeyaml.nodes.MappingNode;
134 import org.yaml.snakeyaml.nodes.Node;
135 import org.yaml.snakeyaml.nodes.NodeTuple;
136 import org.yaml.snakeyaml.nodes.Tag;
137 import org.yaml.snakeyaml.representer.Represent;
138 import org.yaml.snakeyaml.representer.Representer;
141 @org.springframework.stereotype.Component("tosca-export-handler")
142 public class ToscaExportHandler {
144 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
145 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
146 private static final String INVARIANT_UUID = "invariantUUID";
147 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
148 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
149 private static final String IMPORTS_FILE_KEY = "file";
150 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
151 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
152 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
153 private static final String NATIVE_ROOT = "tosca.nodes.Root";
154 private static final YamlUtil yamlUtil = new YamlUtil();
155 private ApplicationDataTypeCache dataTypeCache;
156 private ToscaOperationFacade toscaOperationFacade;
157 private CapabilityRequirementConverter capabilityRequirementConverter;
158 private PolicyExportParser policyExportParser;
159 private GroupExportParser groupExportParser;
160 private PropertyConvertor propertyConvertor;
161 private InputConverter inputConverter;
162 private OutputConverter outputConverter;
163 private InterfaceLifecycleOperation interfaceLifecycleOperation;
164 private InterfacesOperationsConverter interfacesOperationsConverter;
167 public ToscaExportHandler(final ApplicationDataTypeCache dataTypeCache, final ToscaOperationFacade toscaOperationFacade,
168 final CapabilityRequirementConverter capabilityRequirementConverter, final PolicyExportParser policyExportParser,
169 final GroupExportParser groupExportParser, final PropertyConvertor propertyConvertor,
170 final InputConverter inputConverter, final OutputConverter outputConverter,
171 final InterfaceLifecycleOperation interfaceLifecycleOperation,
172 final InterfacesOperationsConverter interfacesOperationsConverter) {
173 this.dataTypeCache = dataTypeCache;
174 this.toscaOperationFacade = toscaOperationFacade;
175 this.capabilityRequirementConverter = capabilityRequirementConverter;
176 this.policyExportParser = policyExportParser;
177 this.groupExportParser = groupExportParser;
178 this.propertyConvertor = propertyConvertor;
179 this.inputConverter = inputConverter;
180 this.outputConverter = outputConverter;
181 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
182 this.interfacesOperationsConverter = interfacesOperationsConverter;
185 public static String getInterfaceFilename(String artifactName) {
186 return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME;
189 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
190 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
193 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
194 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
197 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
198 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
201 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
202 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
203 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
204 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
205 return Either.right(ToscaError.GENERAL_ERROR);
207 String toscaVersion = null;
208 if (component instanceof Resource) {
209 toscaVersion = ((Resource) component).getToscaVersion();
211 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
212 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
213 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
214 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
215 isAssociatedComponent);
216 if (toscaTemplateRes.isRight()) {
217 return Either.right(toscaTemplateRes.right().value());
219 toscaTemplate = toscaTemplateRes.left().value();
220 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
221 return Either.left(toscaRepresentation);
224 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
225 CustomRepresenter representer = new CustomRepresenter();
226 DumperOptions options = new DumperOptions();
227 options.setAllowReadOnlyProperties(false);
228 options.setPrettyFlow(true);
229 options.setDefaultFlowStyle(FlowStyle.FLOW);
230 options.setCanonical(false);
231 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
232 representer.setPropertyUtils(new UnsortedPropertyUtils());
233 Yaml yaml = new Yaml(representer, options);
234 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
235 StringBuilder sb = new StringBuilder();
236 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader());
237 sb.append(yamlAsString);
238 sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter());
239 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
242 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
243 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
244 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
245 if (fillImports.isRight()) {
246 return Either.right(fillImports.right().value());
248 return Either.left(fillImports.left().value().left);
251 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
252 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
253 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
254 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
255 return Either.right(ToscaError.GENERAL_ERROR);
257 log.trace("start tosca export for {}", component.getUniqueId());
258 String toscaVersion = null;
259 if (component instanceof Resource) {
260 toscaVersion = ((Resource) component).getToscaVersion();
262 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
263 toscaTemplate.setMetadata(convertMetadata(component));
264 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
265 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
266 if (ModelConverter.isAtomicComponent(component)) {
267 log.trace("convert component as node type");
268 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
270 log.trace("convert component as topology template");
271 return convertToscaTemplate(component, toscaTemplate);
275 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
276 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
277 if (importsRes.isRight()) {
278 return Either.right(importsRes.right().value());
280 toscaNode = importsRes.left().value().left;
281 Map<String, Component> componentCache = importsRes.left().value().right;
282 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
283 if (nodeTypesMapEither.isRight()) {
284 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
285 return Either.right(nodeTypesMapEither.right().value());
287 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
288 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
289 toscaNode.setNode_types(nodeTypesMap);
291 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
292 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
293 if (proxyInterfaceTypesEither.isRight()) {
294 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
295 return Either.right(proxyInterfaceTypesEither.right().value());
297 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
298 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
299 toscaNode.setInterface_types(proxyInterfaceTypes);
301 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
302 if (dataTypesEither.isRight()) {
303 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
304 return Either.right(ToscaError.GENERAL_ERROR);
306 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
307 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
308 List<InputDefinition> inputDef = component.getInputs();
309 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
310 if (!inputs.isEmpty()) {
311 topologyTemplate.setInputs(inputs);
313 final Map<String, ToscaProperty> outputs;
315 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
316 } catch (final ToscaConversionException e) {
317 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
318 "Could not parse component '{}' outputs. Component unique id '{}'.", new Object[]{component.getName(), component.getUniqueId(), e});
319 return Either.right(ToscaError.GENERAL_ERROR);
321 if (!outputs.isEmpty()) {
322 topologyTemplate.setOutputs(outputs);
324 final List<ComponentInstance> componentInstances = component.getComponentInstances();
325 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
326 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
327 if (CollectionUtils.isNotEmpty(componentInstances)) {
328 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = convertNodeTemplates(component, componentInstances,
329 componentInstancesProperties, componentInstanceInterfaces, componentCache, dataTypes, topologyTemplate);
330 if (nodeTemplates.isRight()) {
331 return Either.right(nodeTemplates.right().value());
333 log.debug("node templates converted");
334 topologyTemplate.setNode_templates(nodeTemplates.left().value());
336 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
337 .createFrom(topologyTemplate.getNode_templates());
338 if (!relationshipTemplatesMap.isEmpty()) {
339 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
341 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
342 convertSubstitutionMappingFilter(component, substitutionMapping);
343 addGroupsToTopologyTemplate(component, topologyTemplate);
345 addPoliciesToTopologyTemplate(component, topologyTemplate);
346 } catch (SdcResourceNotFoundException e) {
347 log.debug("Fail to add policies to topology template:", e);
348 return Either.right(ToscaError.GENERAL_ERROR);
350 String toscaResourceName;
351 switch (component.getComponentType()) {
353 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
354 .getToscaResourceName();
357 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
360 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
361 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
363 substitutionMapping.setNode_type(toscaResourceName);
364 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
365 if (capabilities.isRight()) {
366 return Either.right(capabilities.right().value());
368 substitutionMapping = capabilities.left().value();
369 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
370 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
371 if (requirements.isRight()) {
372 return Either.right(requirements.right().value());
374 substitutionMapping = requirements.left().value();
375 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
376 if (!propertyMappingMap.isEmpty()) {
377 substitutionMapping.setProperties(propertyMappingMap);
379 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
380 if (!attributesMappingMap.isEmpty()) {
381 substitutionMapping.setAttributes(attributesMappingMap);
383 topologyTemplate.setSubstitution_mappings(substitutionMapping);
384 toscaNode.setTopology_template(topologyTemplate);
385 return Either.left(toscaNode);
388 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
389 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
390 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
394 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
395 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
396 if (groups != null) {
397 topologyTemplate.addGroups(groups);
401 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
402 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
403 if (policies != null) {
404 topologyTemplate.addPolicies(policies);
408 private Map<String, String> convertMetadata(Component component) {
409 return convertMetadata(component, false, null);
412 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
413 Map<String, String> toscaMetadata = new LinkedHashMap<>();
414 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
415 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
417 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
418 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
419 List<CategoryDefinition> categories = component.getCategories();
420 CategoryDefinition categoryDefinition = categories.get(0);
421 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
423 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
424 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
425 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
426 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
427 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
428 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
429 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
430 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
431 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
432 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
433 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
434 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
435 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
437 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
440 switch (component.getComponentType()) {
442 Resource resource = (Resource) component;
443 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
444 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
445 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
447 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
449 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
450 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
451 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
452 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
455 Service service = (Service) component;
456 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
457 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
458 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
459 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
460 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
461 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
462 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
465 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
466 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
467 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
471 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
473 for (final String key : component.getCategorySpecificMetadata().keySet()) {
474 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
476 return toscaMetadata;
479 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
480 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
481 return INVARIANT_UUID;
483 return jsonPresentationField.getPresentation();
486 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
487 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
488 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
489 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
490 return Either.right(ToscaError.GENERAL_ERROR);
492 Map<String, Component> componentCache = new HashMap<>();
493 if (!ModelConverter.isAtomicComponent(component)) {
494 final List<Map<String, Map<String, String>>> additionalImports =
495 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
496 List<Triple<String, String, Component>> dependecies = new ArrayList<>();
497 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
498 if (isNotEmpty(toscaArtifacts)) {
499 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
500 if (artifactDefinition != null) {
501 Map<String, Map<String, String>> importsListMember = new HashMap<>();
502 Map<String, String> interfaceFiles = new HashMap<>();
503 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
504 StringBuilder keyNameBuilder = new StringBuilder();
505 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
506 .append("-interface");
507 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
508 additionalImports.add(importsListMember);
511 List<ComponentInstance> componentInstances = component.getComponentInstances();
512 if (componentInstances != null && !componentInstances.isEmpty()) {
513 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci));
515 toscaTemplate.setDependencies(dependecies);
516 toscaTemplate.setImports(additionalImports);
518 log.debug("currently imports supported for VF and service only");
520 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
523 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
524 return ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports();
527 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
528 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
529 log.debug("createDependency componentCache {}", componentCache);
530 Component componentRI = componentCache.get(componentInstance.getComponentUid());
531 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
532 // all resource must be only once!
533 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
534 if ((resource.isRight()) && (log.isDebugEnabled())) {
535 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
536 componentInstance.getUniqueId());
539 final Component fetchedComponent = resource.left().value();
540 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
541 addDependencies(imports, dependencies, componentRI);
546 * Sets a componentCache from the given component/resource.
548 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
549 final Component fetchedComponent) {
550 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
551 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
552 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
553 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
554 .getToscaFullElement(componentInstance.getSourceModelUid());
555 if (sourceService.isRight() && (log.isDebugEnabled())) {
556 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
557 componentInstance.getUniqueId());
559 final Component fetchedSource = sourceService.left().value();
560 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
561 return fetchedSource;
563 return fetchedComponent;
567 * Retrieves all derived_from nodes and stores it in a predictable order.
569 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
570 final Component fetchedComponent) {
571 final Set<Component> componentsList = new LinkedHashSet<>();
572 if (fetchedComponent instanceof Resource) {
573 log.debug("fetchedComponent is a resource {}", fetchedComponent);
574 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
575 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
576 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
577 log.debug("Started entry.getValue() : {}", entry.getValue());
578 if (!NATIVE_ROOT.equals(entry.getValue())) {
579 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
580 if (resourcefetched != null && resourcefetched.isLeft()) {
581 componentsList.add(resourcefetched.left().value());
585 setImports(imports, dependencies, componentsList);
587 setImports(imports, dependencies, fetchedComponent);
593 * Returns all derived_from nodes found.
595 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
596 final Resource parentResource = (Resource) fetchedComponent;
597 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
598 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
599 componentsList.add(fetchedComponent);
600 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
601 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
602 .getToscaElement(componentInstance.getComponentUid());
603 if (resourcefetched != null && resourcefetched.isLeft()) {
604 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
605 if (MapUtils.isNotEmpty(derivedWithId)) {
606 derivedFromMapOfIdToName.putAll(derivedWithId);
611 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
613 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
614 return Optional.ofNullable(derivedFromMapOfIdToName);
618 * Creates a resource map and adds it to the import list.
620 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
621 final Set<Component> componentsList) {
622 componentsList.forEach(component -> setImports(imports, dependencies, component));
625 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
626 final Component component) {
627 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
628 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
629 if (artifactDefinition != null) {
630 final Map<String, String> files = new HashMap<>();
631 final String artifactName = artifactDefinition.getArtifactName();
632 files.put(IMPORTS_FILE_KEY, artifactName);
633 final StringBuilder keyNameBuilder = new StringBuilder();
634 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
635 keyNameBuilder.append("-");
636 keyNameBuilder.append(component.getName());
637 addImports(imports, keyNameBuilder, files);
638 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
639 if (!ModelConverter.isAtomicComponent(component)) {
640 final Map<String, String> interfaceFiles = new HashMap<>();
641 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
642 keyNameBuilder.append("-interface");
643 addImports(imports, keyNameBuilder, interfaceFiles);
649 * Adds the found resource to the import definition list.
651 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
652 final Map<String, String> files) {
653 final String mapKey = keyNameBuilder.toString();
654 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
655 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
656 importsListMember.put(keyNameBuilder.toString(), files);
657 imports.add(importsListMember);
661 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
662 Map<String, ToscaNodeType> nodeTypes) {
663 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
666 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
667 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
668 boolean isAssociatedComponent) {
669 log.debug("start convert node type for {}", component.getUniqueId());
670 ToscaNodeType toscaNodeType = createNodeType(component);
671 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
672 .getAllInterfaceLifecycleTypes();
673 if (lifecycleTypeEither.isRight()) {
674 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
675 return Either.right(ToscaError.GENERAL_ERROR);
677 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
678 .collect(Collectors.toList());
679 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
680 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
681 if (dataTypesEither.isRight()) {
682 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
683 return Either.right(ToscaError.GENERAL_ERROR);
685 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
686 List<InputDefinition> inputDef = component.getInputs();
687 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
688 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
689 addInputsToProperties(dataTypes, inputDef, mergedProperties);
690 final Map<String, ToscaAttribute> toscaAttributeMap;
692 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
693 } catch (final ToscaConversionException e) {
694 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
695 "Could not parse component '{}' attributes. Component unique id '{}'.",
696 new Object[]{component.getName(), component.getUniqueId(), e});
697 return Either.right(ToscaError.GENERAL_ERROR);
699 if (!toscaAttributeMap.isEmpty()) {
700 toscaNodeType.setAttributes(toscaAttributeMap);
702 if (CollectionUtils.isNotEmpty(component.getProperties())) {
703 List<PropertyDefinition> properties = component.getProperties();
704 Map<String, ToscaProperty> convertedProperties = properties.stream()
705 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
706 .toMap(PropertyDataDefinition::getName,
707 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
708 // merge component properties and inputs properties
709 mergedProperties.putAll(convertedProperties);
711 if (MapUtils.isNotEmpty(mergedProperties)) {
712 toscaNodeType.setProperties(mergedProperties);
714 /* convert private data_types */
715 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
716 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
717 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
718 for (DataTypeDefinition dataType : privateDataTypes) {
719 log.debug("Emitting private data type: component.name={} dataType.name={}",
720 component.getNormalizedName(), dataType.getName());
721 ToscaDataType toscaDataType = new ToscaDataType();
722 toscaDataType.setDerived_from(dataType.getDerivedFromName());
723 toscaDataType.setDescription(dataType.getDescription());
724 toscaDataType.setVersion(dataType.getVersion());
725 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
726 toscaDataType.setProperties(dataType.getProperties().stream()
727 .collect(Collectors.toMap(
728 PropertyDataDefinition::getName,
729 s -> propertyConvertor
730 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
733 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
735 toscaNode.setData_types(toscaDataTypeMap);
738 // Extracted to method for code reuse
739 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
742 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
743 final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
744 if (CollectionUtils.isEmpty(attributeList)) {
745 return Collections.emptyMap();
747 final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
748 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
749 for (final AttributeDefinition attributeDefinition : attributeList) {
750 toscaAttributeMap.put(attributeDefinition.getName(), attributeConverter.convert(attributeDefinition));
752 return toscaAttributeMap;
755 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
756 Component component, ToscaTemplate toscaNode,
757 Map<String, ToscaNodeType> nodeTypes,
758 ToscaNodeType toscaNodeType,
759 Map<String, DataTypeDefinition> dataTypes) {
760 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
762 if (capabilities.isRight()) {
763 return Either.right(capabilities.right().value());
765 toscaNodeType = capabilities.left().value();
766 log.debug("Capabilities converted for {}", component.getUniqueId());
768 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
769 .convertRequirements(componentsCache, component,
771 if (requirements.isRight()) {
772 return Either.right(requirements.right().value());
774 toscaNodeType = requirements.left().value();
775 log.debug("Requirements converted for {}", component.getUniqueId());
777 String toscaResourceName;
778 switch (component.getComponentType()) {
780 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
781 .getMetadataDataDefinition()).getToscaResourceName();
784 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
785 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
788 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
789 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
792 nodeTypes.put(toscaResourceName, toscaNodeType);
793 toscaNode.setNode_types(nodeTypes);
794 log.debug("finish convert node type for {}", component.getUniqueId());
795 return Either.left(toscaNode);
798 protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(
800 List<ComponentInstance> componentInstances,
801 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
802 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
803 Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes,
804 ToscaTopolgyTemplate topologyTemplate) {
806 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
807 log.debug("start convert topology template for {} for type {}", component.getUniqueId(),
808 component.getComponentType());
809 Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
810 Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
812 Map<String, ToscaGroupTemplate> groupsMap = null;
813 for (ComponentInstance componentInstance : componentInstances) {
814 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
815 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
816 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
818 nodeTemplate.setType(componentInstance.getToscaComponentName());
819 nodeTemplate.setDirectives(componentInstance.getDirectives());
820 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
822 Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
823 .getOriginComponent(componentCache, componentInstance);
824 if (originComponentRes.isRight()) {
825 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
828 Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component,
829 componentInstance, component.getComponentInstancesRelations(), nodeTemplate,
830 originComponentRes.left().value(), componentCache);
831 if (requirements.isRight()) {
832 convertNodeTemplatesRes = Either.right(requirements.right().value());
835 String instanceUniqueId = componentInstance.getUniqueId();
836 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
838 nodeTemplate = requirements.left().value();
840 Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
842 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
843 Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
844 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
846 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
849 Either<ToscaNodeTemplate, ToscaError> capabilities = capabilityRequirementConverter
850 .convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
851 if (capabilities.isRight()) {
852 convertNodeTemplatesRes = Either.right(capabilities.right().value());
855 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
857 nodeTemplate = capabilities.left().value();
858 Map<String, Object> props = new HashMap<>();
860 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
861 // Adds the properties of parent component to map
862 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
865 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
866 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId,
870 if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)
871 && !isComponentOfTypeServiceProxy(componentInstance)) {
872 //For service proxy the inputs are already handled under instance properties above
873 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
876 //M3[00001] - NODE TEMPLATE INTERFACES - START
877 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate,
878 instanceUniqueId, component);
879 //M3[00001] - NODE TEMPLATE INTERFACES - END
880 if (props != null && !props.isEmpty()) {
881 nodeTemplate.setProperties(props);
884 List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
885 if (groupInstances != null) {
886 if (groupsMap == null) {
887 groupsMap = new HashMap<>();
889 for (GroupInstance groupInst : groupInstances) {
890 boolean addToTosca = true;
892 List<String> artifacts = groupInst.getArtifacts();
893 if (artifacts == null || artifacts.isEmpty()) {
898 ToscaGroupTemplate toscaGroup = groupExportParser
899 .getToscaGroupTemplate(groupInst, componentInstance.getInvariantName());
900 groupsMap.put(groupInst.getName(), toscaGroup);
905 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
907 if (groupsMap != null) {
908 log.debug("instance groups added");
909 topologyTemplate.addGroups(groupsMap);
911 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
912 ((Service) component).getForwardingPaths())) {
913 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(),
914 component.getName());
915 ForwardingPathToscaUtil
916 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache,
917 toscaOperationFacade);
918 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(),
919 component.getName());
921 if (convertNodeTemplatesRes == null) {
922 convertNodeTemplatesRes = Either.left(nodeTemplates);
924 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(),
925 component.getComponentType());
926 return convertNodeTemplatesRes;
929 private void handleInstanceInterfaces(
930 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
931 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
932 String instanceUniqueId,
933 Component parentComponent) {
935 if (MapUtils.isEmpty(componentInstanceInterfaces)
936 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
937 nodeTemplate.setInterfaces(null);
941 final List<ComponentInstanceInterface> currServiceInterfaces =
942 componentInstanceInterfaces.get(instanceUniqueId);
944 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
945 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
946 .getUniqueId(), instInterface));
948 final Map<String, Object> interfaceMap = interfacesOperationsConverter
949 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
950 isComponentOfTypeServiceProxy(componentInstance));
952 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
953 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
956 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
957 return Objects.nonNull(componentInstance.getOriginType())
958 && componentInstance.getOriginType().getValue().equals("Service Proxy");
961 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
962 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
963 String instanceUniqueId, Map<String, Object> props) {
965 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
966 if (instanceInputsList != null) {
967 instanceInputsList.forEach(input -> {
969 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
970 ? input.getValue() : input.getDefaultValue();
971 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
976 private void addPropertiesOfComponentInstance(
977 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
978 Map<String, DataTypeDefinition> dataTypes, String instanceUniqueId,
979 Map<String, Object> props) {
981 if (isNotEmpty(componentInstancesProperties)) {
982 componentInstancesProperties.get(instanceUniqueId)
983 // Converts and adds each value to property map
984 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
989 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
990 Component componentOfInstance, Map<String, Object> props) {
992 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
993 if (isNotEmpty(componentProperties)) {
994 componentProperties.stream()
995 // Filters out properties with empty default values
996 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
997 // Converts and adds each value to property map
998 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
999 prop::getDefaultValue));
1003 private ToscaNodeType createNodeType(Component component) {
1004 ToscaNodeType toscaNodeType = new ToscaNodeType();
1005 if (ModelConverter.isAtomicComponent(component)) {
1006 if (((Resource) component).getDerivedFrom() != null) {
1007 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1009 toscaNodeType.setDescription(component.getDescription());
1011 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1013 toscaNodeType.setDerived_from(derivedFrom);
1015 return toscaNodeType;
1018 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1020 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1021 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1022 List<ComponentInstance> componentInstances = container.getComponentInstances();
1023 if (CollectionUtils.isEmpty(componentInstances)) {
1026 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1027 componentInstances.stream()
1028 .filter(this::isComponentOfTypeServiceProxy)
1029 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1030 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1033 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1034 Component serviceComponent;
1035 ComponentParametersView componentParametersView = new ComponentParametersView();
1036 componentParametersView.disableAll();
1037 componentParametersView.setIgnoreInterfaces(false);
1038 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1039 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1040 if (service.isRight()) {
1041 log.debug("Failed to fetch original service component with id {} for instance {}",
1042 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1043 return Either.right(ToscaError.GENERAL_ERROR);
1045 serviceComponent = service.left().value();
1048 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1049 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes();
1050 if (lifecycleTypeEither.isRight()) {
1051 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1052 return Either.right(ToscaError.GENERAL_ERROR);
1055 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1056 .map(InterfaceDataDefinition::getType)
1057 .collect(Collectors.toList());
1058 //Add interface types for local interfaces in the original service component for proxy
1059 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1060 allGlobalInterfaceTypes);
1061 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1062 proxyInterfaceTypes.putAll(localInterfaceTypes);
1066 return Either.left(proxyInterfaceTypes);
1069 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1070 Component container) {
1072 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1073 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1075 List<ComponentInstance> componentInstances = container.getComponentInstances();
1077 if (componentInstances == null || componentInstances.isEmpty()) {
1080 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1081 List<ComponentInstance> proxyInst = componentInstances.stream()
1082 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1083 .collect(Collectors.toList());
1084 if (proxyInst != null && !proxyInst.isEmpty()) {
1085 for (ComponentInstance inst : proxyInst) {
1086 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1090 if (serviceProxyInstanceList.isEmpty()) {
1093 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1094 .getLatestByName("serviceProxy");
1095 if (serviceProxyOrigin.isRight()) {
1096 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1097 serviceProxyOrigin.right().value());
1098 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1100 Component origComponent = serviceProxyOrigin.left().value();
1102 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1103 Component serviceComponent = null;
1104 ComponentParametersView componentParametersView = new ComponentParametersView();
1105 componentParametersView.disableAll();
1106 componentParametersView.setIgnoreCategories(false);
1107 componentParametersView.setIgnoreProperties(false);
1108 componentParametersView.setIgnoreInputs(false);
1109 componentParametersView.setIgnoreInterfaces(false);
1110 componentParametersView.setIgnoreRequirements(false);
1111 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1112 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1113 if (service.isRight()) {
1114 log.debug("Failed to fetch resource with id {} for instance {}",
1115 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1117 serviceComponent = service.left().value();
1120 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1121 entryProxy.getValue());
1122 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1125 return Either.left(nodeTypesMap);
1128 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1129 final Component container, final ToscaTemplate toscaNode) {
1130 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1132 if (CollectionUtils.isEmpty(componentInstances)) {
1135 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1136 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1137 .collect(Collectors.toList());
1138 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1139 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1140 final Map<String, ToscaNodeType> nodeTypes =
1141 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1142 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1148 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1149 Component proxyComponent, ComponentInstance componentInstance) {
1150 ToscaNodeType toscaNodeType = new ToscaNodeType();
1151 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1153 toscaNodeType.setDerived_from(derivedFrom);
1154 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = dataTypeCache.getAll();
1155 if (dataTypesEither.isRight()) {
1156 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1158 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1159 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1160 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1162 if (MapUtils.isNotEmpty(capabilities)) {
1163 toscaNodeType.setCapabilities(capabilities);
1165 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1166 .convertProxyRequirements(componentCache, componentInstance);
1167 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1168 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1170 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1171 proxyProperties.ifPresent(toscaNodeType::setProperties);
1173 Map<String, Object> interfaceMap = new HashMap<>();
1174 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1175 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1176 if (proxyInterfaces.isPresent()) {
1177 interfaceMap = proxyInterfaces.get();
1180 interfaceMap = interfacesOperationsConverter
1181 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1184 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1185 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1187 return toscaNodeType;
1190 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1191 ComponentInstance componentInstance,
1192 List<RequirementCapabilityRelDef> relations,
1193 ToscaNodeTemplate nodeTypeTemplate,
1194 Component originComponent,
1195 Map<String, Component> componentCache) {
1197 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements;
1198 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1200 if (isNotEmpty(requirementDefinitionList)) {
1202 toscaRequirements = buildRequirements(component, componentInstance,
1203 requirementDefinitionList, originComponent, componentCache);
1204 if (!toscaRequirements.isEmpty()) {
1205 nodeTypeTemplate.setRequirements(toscaRequirements);
1207 } catch (final Exception e) {
1208 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1209 componentInstance.getName(), e);
1210 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1213 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1214 return Either.left(nodeTypeTemplate);
1217 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1218 final ComponentInstance componentInstance,
1219 final List<RequirementCapabilityRelDef> filteredRelations,
1220 final Component originComponent,
1221 final Map<String, Component> componentCache)
1222 throws ToscaExportException {
1224 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1225 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1226 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1227 buildRequirement(componentInstance, originComponent, component.getComponentInstances(),
1228 relationshipDefinition, componentCache);
1229 toscaRequirements.add(toscaTemplateRequirementMap);
1232 return toscaRequirements;
1235 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1236 List<RequirementCapabilityRelDef> relations) {
1237 return relations.stream()
1238 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1241 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1242 final Component fromOriginComponent,
1243 final List<ComponentInstance> instancesList,
1244 final RequirementCapabilityRelDef relationshipDefinition,
1245 final Map<String, Component> componentCache)
1246 throws ToscaExportException {
1248 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1249 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1250 .getRelationships().get(0);
1251 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1253 final ComponentInstance toInstance = instancesList.stream()
1254 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1255 .findFirst().orElse(null);
1256 if (toInstance == null) {
1257 final String errorMsg = String
1258 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1259 relationshipDefinition.getToNode());
1260 log.debug(errorMsg);
1261 throw new ToscaExportException(errorMsg);
1263 final Optional<RequirementDefinition> reqOpt =
1264 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1265 if (reqOpt.isEmpty()) {
1266 final String errorMsg = String
1267 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1268 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1269 log.debug(errorMsg);
1270 throw new ToscaExportException(errorMsg);
1272 final ComponentParametersView filter = new ComponentParametersView(true);
1273 filter.setIgnoreComponentInstances(false);
1274 filter.setIgnoreCapabilities(false);
1275 filter.setIgnoreGroups(false);
1276 final Either<Component, StorageOperationStatus> getOriginRes =
1277 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1278 if (getOriginRes.isRight()) {
1279 final String errorMsg = String.format(
1280 "Failed to build substituted name for the requirement %s. "
1281 + "Failed to get an origin component with uniqueId %s",
1282 reqOpt.get().getName(), toInstance.getActualComponentUid());
1283 log.debug(errorMsg);
1284 throw new ToscaExportException(errorMsg);
1286 final Component toOriginComponent = getOriginRes.left().value();
1287 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1288 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1289 if (capOpt.isEmpty()) {
1290 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1291 if (capOpt.isEmpty()) {
1292 final String errorMsg = String
1293 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1294 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1295 log.debug(errorMsg);
1296 throw new ToscaExportException(errorMsg);
1299 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1300 capabilityRequirementRelationship, toInstance, componentCache);
1303 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1304 CapabilityDefinition capability) {
1305 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1306 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1309 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1310 Component toOriginComponent, Component fromOriginComponent,
1311 RequirementDefinition requirement) {
1312 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1313 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1314 if (!cap.isPresent()) {
1315 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1316 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1321 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1322 final Component toOriginComponent,
1323 final CapabilityDefinition capability,
1324 final RequirementDefinition requirement,
1325 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1326 final ComponentInstance toInstance,
1327 final Map<String, Component> componentCache)
1328 throws ToscaExportException {
1330 List<String> reducedPath = capability.getPath();
1331 if (capability.getOwnerId() != null) {
1332 reducedPath = capabilityRequirementConverter
1333 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1335 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1336 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1337 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1338 if (capabilityNameEither.isRight()) {
1339 final String errorMsg = String.format(
1340 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1341 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1344 throw new ToscaExportException(errorMsg);
1346 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1347 .buildSubstitutedName(componentCache, fromOriginComponent,
1348 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1349 if (requirementNameEither.isRight()) {
1350 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1351 + "with name %s on a component with uniqueId %s",
1352 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1353 log.debug(errorMsg);
1354 throw new ToscaExportException(errorMsg);
1356 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1357 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1358 toscaRequirement.setNode(toInstance.getName());
1359 toscaRequirement.setCapability(capabilityNameEither.left().value());
1360 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1361 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1363 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1367 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1368 Map<String, List<RequirementDefinition>> reqMap,
1369 RelationshipInfo reqAndRelationshipPair,
1370 String fromInstanceId) {
1371 for (List<RequirementDefinition> reqList : reqMap.values()) {
1372 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1373 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1375 if (reqOpt.isPresent()) {
1379 return Optional.empty();
1383 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1384 * 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
1385 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1387 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1388 RequirementDefinition requirement, String fromInstanceId) {
1389 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1390 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1391 reqAndRelationshipPair.getRequirement());
1394 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1398 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1399 Component originComponent) {
1400 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1401 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1402 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1405 private boolean isCvfc(Component component) {
1406 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1409 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1410 Map<String, Component> componentCache) {
1411 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1412 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1413 .convertSubstitutionMappingCapabilities(componentCache, component);
1414 if (toscaCapabilitiesRes.isRight()) {
1415 result = Either.right(toscaCapabilitiesRes.right().value());
1416 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1417 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1418 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1419 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1421 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1425 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1426 Map<String, DataTypeDefinition> dataTypes) {
1427 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1428 if (!toscaCapabilities.isEmpty()) {
1429 nodeType.setCapabilities(toscaCapabilities);
1431 log.debug("Finish convert Capabilities for node type");
1432 return Either.left(nodeType);
1435 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1436 if (artifacts == null) {
1439 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1440 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1441 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1442 artifact.setFile(entry.getValue().getFile());
1443 artifact.setType(entry.getValue().getType());
1444 arts.put(entry.getKey(), artifact);
1449 protected NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1450 if (inNodeFilter == null) {
1453 NodeFilter nodeFilter = new NodeFilter();
1454 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1455 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1456 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1457 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1458 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1459 copyNodeFilterProperties(origProperties, propertiesCopy);
1460 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1461 nodeFilter.setCapabilities(capabilitiesCopy);
1463 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1464 nodeFilter.setProperties(propertiesCopy);
1466 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1467 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1471 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1472 if (substitutionFilterDataDefinition == null) {
1475 NodeFilter nodeFilter = new NodeFilter();
1476 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1477 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1478 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1479 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1480 nodeFilter.setProperties(propertiesCopy);
1482 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1483 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1486 private Object cloneToscaId(Object toscaId) {
1487 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1490 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1491 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1492 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1495 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1496 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1497 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1501 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1502 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1503 CapabilityFilter capabilityFilter = new CapabilityFilter();
1504 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1505 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1506 capabilityFilter.setProperties(propertiesCopy);
1507 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1508 capabilitiesCopy.add(capabilityFilterCopyMap);
1512 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1513 List<Map<String, List<Object>>> propertiesCopy) {
1514 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1517 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1518 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1519 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1520 Map propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1521 String propertyName = propertyDataDefinition.getName();
1522 if (propertyMapCopy.containsKey(propertyName)) {
1523 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1525 if (propertyName != null) {
1526 List<Object> propsList = new ArrayList<>();
1527 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1528 propertyMapCopy.put(propertyName, propsList);
1530 propertyMapCopy.putAll(propertyValObj);
1535 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1538 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1539 final List<Map<String, List<Object>>> propertiesCopy) {
1540 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1543 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1544 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1545 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1546 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1547 final String propertyName = propertyDataDefinition.getName();
1548 if (propertyMapCopy.containsKey(propertyName)) {
1549 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1551 if (propertyName != null) {
1552 final List<Object> propsList = new ArrayList<>();
1553 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1554 propertyMapCopy.put(propertyName, propsList);
1556 propertyMapCopy.putAll(propertyValObj);
1561 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1564 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1565 if (propertyValObj.containsKey(propertyName)) {
1566 propsList.add(propertyValObj.get(propertyName));
1568 propsList.add(propertyValObj);
1572 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1573 Map<String, List<Object>> tempMap = new HashMap<>();
1574 tempMap.put(entry.getKey(), entry.getValue());
1575 propertiesCopy.add(tempMap);
1578 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1579 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1580 return Collections.emptyMap();
1582 return component.getInputs().stream().filter(input -> input.isMappedToComponentProperty()).map(PropertyDataDefinition::getName)
1583 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1586 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1587 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1588 return Collections.emptyMap();
1590 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1591 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1594 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1595 if (Objects.isNull(proxyComponent)) {
1596 return Optional.empty();
1598 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1599 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1600 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1601 proxyProperties.putAll(proxyComponent.getProperties().stream()
1602 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1603 .toMap(PropertyDataDefinition::getName,
1604 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1606 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1609 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1610 Map<String, ToscaProperty> mergedProperties) {
1611 if (CollectionUtils.isEmpty(componentInputs)) {
1614 for (InputDefinition input : componentInputs) {
1615 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1616 mergedProperties.put(input.getName(), property);
1620 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1621 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1622 return Optional.empty();
1624 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1625 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1627 // always available in the proxy node template
1628 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1630 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1633 private static class CustomRepresenter extends Representer {
1635 CustomRepresenter() {
1637 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1638 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1639 // null representer is exceptional and it is stored as an instance
1642 this.nullRepresenter = new RepresentNull();
1645 public boolean validateGetInputValue(final Object valueObj) {
1646 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1649 if (valueObj instanceof List) {
1650 return ((List) valueObj).size() > 1;
1655 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1656 if (valueObj instanceof List) {
1657 return ((List) valueObj).size() > 1;
1663 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1664 if (propertyValue == null) {
1667 // skip not relevant for Tosca property
1668 if ("dependencies".equals(property.getName())) {
1671 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1674 removeDefaultP(propertyValue);
1675 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1676 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1677 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1679 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1682 private void removeDefaultP(final Object propertyValue) {
1683 if (propertyValue instanceof Map) {
1684 final Map mapPropertyValue = ((Map) propertyValue);
1685 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1686 Object defaultValue = null;
1687 while (iter.hasNext()) {
1688 final Map.Entry entry = iter.next();
1689 if ("_defaultp_".equals(entry.getKey())) {
1690 defaultValue = entry.getValue();
1692 } else if (entry.getValue() instanceof Map) {
1693 removeDefaultP(entry.getValue());
1696 if (defaultValue != null) {
1697 mapPropertyValue.putIfAbsent("default", defaultValue);
1703 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1704 // remove the bean type from the output yaml (!! ...)
1705 if (!classTags.containsKey(javaBean.getClass())) {
1706 addClassTag(javaBean.getClass(), Tag.MAP);
1708 return super.representJavaBean(properties, javaBean);
1711 private class RepresentToscaAttribute implements Represent {
1714 public Node representData(Object data) {
1715 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1716 return represent(toscaAttribute.asToscaMap());
1720 private class RepresentToscaPropertyAssignment implements Represent {
1722 public Node representData(Object data) {
1723 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1724 if (toscaOperationAssignment.getValue() instanceof String) {
1725 final String stringValue = (String) toscaOperationAssignment.getValue();
1726 if (isPropertyOrAttributeFunction(stringValue)) {
1727 return representGetAttribute(stringValue);
1729 return representScalar(Tag.STR, stringValue);
1731 return represent(null);
1734 public Node representGetAttribute(final String getAttributeFunction) {
1735 return represent(new Yaml().load(getAttributeFunction));
1738 public boolean isPropertyOrAttributeFunction(final String value) {
1740 final Yaml yaml = new Yaml();
1741 final Object yamlObj = yaml.load(value);
1742 if (!(yamlObj instanceof Map)) {
1745 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1746 if (getAttributeMap.size() != 1) {
1749 final List<String> functionList = Arrays
1750 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1751 final Optional<String> function = getAttributeMap.keySet().stream()
1752 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1753 if (function.isEmpty()) {
1756 final String functionName = function.get();
1757 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1758 if (GET_INPUT.getFunctionName().equals(functionName)) {
1759 return validateGetInputValue(getAttributeValueObj);
1761 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1763 } catch (final Exception ignored) {
1769 private class RepresentNull implements Represent {
1772 public Node representData(Object data) {
1773 // possible values are here http://yaml.org/type/null.html
1774 return representScalar(Tag.NULL, "");
1779 private static class UnsortedPropertyUtils extends PropertyUtils {
1782 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1783 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1784 return new LinkedHashSet<>(fields);