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 org.apache.commons.collections.CollectionUtils;
48 import org.apache.commons.collections.MapUtils;
49 import org.apache.commons.io.FilenameUtils;
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.data.model.ToscaImportByModel;
60 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
61 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
62 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
63 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
64 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
65 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
66 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
67 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
68 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
70 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
71 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
73 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
74 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
75 import org.openecomp.sdc.be.exception.ToscaExportException;
76 import org.openecomp.sdc.be.model.ArtifactDefinition;
77 import org.openecomp.sdc.be.model.AttributeDefinition;
78 import org.openecomp.sdc.be.model.CapabilityDefinition;
79 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
80 import org.openecomp.sdc.be.model.Component;
81 import org.openecomp.sdc.be.model.ComponentInstance;
82 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
83 import org.openecomp.sdc.be.model.ComponentInstanceInput;
84 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
85 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
86 import org.openecomp.sdc.be.model.ComponentParametersView;
87 import org.openecomp.sdc.be.model.DataTypeDefinition;
88 import org.openecomp.sdc.be.model.GroupInstance;
89 import org.openecomp.sdc.be.model.InputDefinition;
90 import org.openecomp.sdc.be.model.InterfaceDefinition;
91 import org.openecomp.sdc.be.model.PropertyDefinition;
92 import org.openecomp.sdc.be.model.RelationshipInfo;
93 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
94 import org.openecomp.sdc.be.model.RequirementDefinition;
95 import org.openecomp.sdc.be.model.Resource;
96 import org.openecomp.sdc.be.model.Service;
97 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
98 import org.openecomp.sdc.be.model.category.CategoryDefinition;
99 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
100 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
101 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
102 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
103 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
104 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
105 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
106 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
107 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
108 import org.openecomp.sdc.be.tosca.model.NodeFilter;
109 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
110 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
111 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
112 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
113 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
114 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
115 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
116 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
117 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
118 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
119 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
120 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
121 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
122 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
123 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
124 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
125 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
126 import org.openecomp.sdc.be.tosca.utils.InputConverter;
127 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
128 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
129 import org.openecomp.sdc.common.log.wrappers.Logger;
130 import org.springframework.beans.factory.annotation.Autowired;
131 import org.yaml.snakeyaml.DumperOptions;
132 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
133 import org.yaml.snakeyaml.Yaml;
134 import org.yaml.snakeyaml.introspector.BeanAccess;
135 import org.yaml.snakeyaml.introspector.Property;
136 import org.yaml.snakeyaml.introspector.PropertyUtils;
137 import org.yaml.snakeyaml.nodes.MappingNode;
138 import org.yaml.snakeyaml.nodes.Node;
139 import org.yaml.snakeyaml.nodes.NodeTuple;
140 import org.yaml.snakeyaml.nodes.Tag;
141 import org.yaml.snakeyaml.representer.Represent;
142 import org.yaml.snakeyaml.representer.Representer;
144 @org.springframework.stereotype.Component("tosca-export-handler")
145 public class ToscaExportHandler {
147 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
148 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
149 private static final String INVARIANT_UUID = "invariantUUID";
150 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
151 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
152 private static final String IMPORTS_FILE_KEY = "file";
153 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
154 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
155 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
156 private static final String NATIVE_ROOT = "tosca.nodes.Root";
157 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
158 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
159 private static final YamlUtil yamlUtil = new YamlUtil();
160 private final ApplicationDataTypeCache applicationDataTypeCache;
161 private final ToscaOperationFacade toscaOperationFacade;
162 private final CapabilityRequirementConverter capabilityRequirementConverter;
163 private final PolicyExportParser policyExportParser;
164 private final GroupExportParser groupExportParser;
165 private final PropertyConvertor propertyConvertor;
166 private final AttributeConverter attributeConverter;
167 private final InputConverter inputConverter;
168 private final OutputConverter outputConverter;
169 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
170 private final InterfacesOperationsConverter interfacesOperationsConverter;
171 private final ModelOperation modelOperation;
174 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
175 final ToscaOperationFacade toscaOperationFacade,
176 final CapabilityRequirementConverter capabilityRequirementConverter,
177 final PolicyExportParser policyExportParser,
178 final GroupExportParser groupExportParser,
179 final PropertyConvertor propertyConvertor,
180 final AttributeConverter attributeConverter,
181 final InputConverter inputConverter,
182 final OutputConverter outputConverter,
183 final InterfaceLifecycleOperation interfaceLifecycleOperation,
184 final InterfacesOperationsConverter interfacesOperationsConverter,
185 final ModelOperation modelOperation) {
186 this.applicationDataTypeCache = applicationDataTypeCache;
187 this.toscaOperationFacade = toscaOperationFacade;
188 this.capabilityRequirementConverter = capabilityRequirementConverter;
189 this.policyExportParser = policyExportParser;
190 this.groupExportParser = groupExportParser;
191 this.propertyConvertor = propertyConvertor;
192 this.attributeConverter = attributeConverter;
193 this.inputConverter = inputConverter;
194 this.outputConverter = outputConverter;
195 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
196 this.interfacesOperationsConverter = interfacesOperationsConverter;
197 this.modelOperation = modelOperation;
200 public static String getInterfaceFilename(String artifactName) {
201 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
204 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
205 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
208 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
209 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
212 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
213 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
216 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
217 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
218 if (CollectionUtils.isEmpty(imports)) {
219 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
220 return Either.right(ToscaError.GENERAL_ERROR);
222 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
223 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
224 .startsWith("org.openecomp.resource.abstract.nodes.")) {
225 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
226 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(), component.getModel());
227 if (baseType.isLeft() && baseType.left().value() != null) {
228 addDependencies(imports, dependencies, baseType.left().value());
230 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
234 String toscaVersion = null;
235 if (component instanceof Resource) {
236 toscaVersion = ((Resource) component).getToscaVersion();
238 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
239 toscaTemplate.setImports(imports);
240 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
241 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
242 isAssociatedComponent);
243 if (toscaTemplateRes.isRight()) {
244 return Either.right(toscaTemplateRes.right().value());
246 toscaTemplate = toscaTemplateRes.left().value();
247 toscaTemplate.setDependencies(dependencies);
248 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
249 return Either.left(toscaRepresentation);
252 public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
253 CustomRepresenter representer = new CustomRepresenter();
254 DumperOptions options = new DumperOptions();
255 options.setAllowReadOnlyProperties(false);
256 options.setPrettyFlow(true);
257 options.setDefaultFlowStyle(FlowStyle.FLOW);
258 options.setCanonical(false);
259 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
260 representer.setPropertyUtils(new UnsortedPropertyUtils());
261 Yaml yaml = new Yaml(representer, options);
262 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
263 StringBuilder sb = new StringBuilder();
264 sb.append(getConfiguration().getHeatEnvArtifactHeader());
265 sb.append(yamlAsString);
266 sb.append(getConfiguration().getHeatEnvArtifactFooter());
267 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
270 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
271 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
272 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
273 if (fillImports.isRight()) {
274 return Either.right(fillImports.right().value());
276 return Either.left(fillImports.left().value().left);
279 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
280 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
281 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
282 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
283 return Either.right(ToscaError.GENERAL_ERROR);
285 log.trace("start tosca export for {}", component.getUniqueId());
286 String toscaVersion = null;
287 if (component instanceof Resource) {
288 toscaVersion = ((Resource) component).getToscaVersion();
290 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
291 toscaTemplate.setMetadata(convertMetadata(component));
292 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
293 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
294 if (ModelConverter.isAtomicComponent(component)) {
295 log.trace("convert component as node type");
296 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
298 log.trace("convert component as topology template");
299 return convertToscaTemplate(component, toscaTemplate);
303 public List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
304 if (modelId == null) {
305 return getDefaultToscaImportConfig();
308 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
309 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
310 for(final ToscaImportByModel toscaImportByModel: allModelImports) {
311 final String fileName = FilenameUtils.getBaseName(toscaImportByModel.getFullPath());
312 importList.add(Map.of(fileName, Map.of("file", toscaImportByModel.getFullPath())));
317 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
318 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
319 if (importsRes.isRight()) {
320 return Either.right(importsRes.right().value());
322 toscaNode = importsRes.left().value().left;
323 Map<String, Component> componentCache = importsRes.left().value().right;
324 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
325 if (nodeTypesMapEither.isRight()) {
326 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
327 return Either.right(nodeTypesMapEither.right().value());
329 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
330 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
331 toscaNode.setNode_types(nodeTypesMap);
333 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
334 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
335 if (proxyInterfaceTypesEither.isRight()) {
336 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
337 return Either.right(proxyInterfaceTypesEither.right().value());
339 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
340 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
341 toscaNode.setInterface_types(proxyInterfaceTypes);
343 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
344 if (dataTypesEither.isRight()) {
345 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
346 return Either.right(ToscaError.GENERAL_ERROR);
348 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
349 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
350 List<InputDefinition> inputDef = component.getInputs();
351 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
352 if (!inputs.isEmpty()) {
353 topologyTemplate.setInputs(inputs);
355 final Map<String, ToscaProperty> outputs;
357 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
358 } catch (final ToscaConversionException e) {
359 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
360 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
361 return Either.right(ToscaError.GENERAL_ERROR);
363 if (!outputs.isEmpty()) {
364 topologyTemplate.setOutputs(outputs);
366 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
367 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
368 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
369 if (nodeTemplates.isRight()) {
370 return Either.right(nodeTemplates.right().value());
372 log.debug("node templates converted");
373 topologyTemplate.setNode_templates(nodeTemplates.left().value());
375 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
376 .createFrom(topologyTemplate.getNode_templates());
377 if (!relationshipTemplatesMap.isEmpty()) {
378 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
380 SubstitutionMapping substitutionMapping = new SubstitutionMapping();
381 convertSubstitutionMappingFilter(component, substitutionMapping);
382 addGroupsToTopologyTemplate(component, topologyTemplate);
384 addPoliciesToTopologyTemplate(component, topologyTemplate);
385 } catch (SdcResourceNotFoundException e) {
386 log.debug("Fail to add policies to topology template:", e);
387 return Either.right(ToscaError.GENERAL_ERROR);
389 String toscaResourceName;
390 switch (component.getComponentType()) {
392 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition())
393 .getToscaResourceName();
396 toscaResourceName = SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
399 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
400 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
402 substitutionMapping.setNode_type(toscaResourceName);
403 Either<SubstitutionMapping, ToscaError> capabilities = convertCapabilities(component, substitutionMapping, componentCache);
404 if (capabilities.isRight()) {
405 return Either.right(capabilities.right().value());
407 substitutionMapping = capabilities.left().value();
408 Either<SubstitutionMapping, ToscaError> requirements = capabilityRequirementConverter
409 .convertSubstitutionMappingRequirements(componentCache, component, substitutionMapping);
410 if (requirements.isRight()) {
411 return Either.right(requirements.right().value());
413 substitutionMapping = requirements.left().value();
414 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
415 if (!propertyMappingMap.isEmpty()) {
416 substitutionMapping.setProperties(propertyMappingMap);
418 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
419 if (!attributesMappingMap.isEmpty()) {
420 substitutionMapping.setAttributes(attributesMappingMap);
422 topologyTemplate.setSubstitution_mappings(substitutionMapping);
423 toscaNode.setTopology_template(topologyTemplate);
424 return Either.left(toscaNode);
427 private void convertSubstitutionMappingFilter(final Component component, final SubstitutionMapping substitutionMapping) {
428 if (component.getSubstitutionFilter() != null && (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() != null) {
429 substitutionMapping.setSubstitution_filter(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
433 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
434 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
435 if (groups != null) {
436 topologyTemplate.addGroups(groups);
440 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
441 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
442 if (policies != null) {
443 topologyTemplate.addPolicies(policies);
447 private Map<String, String> convertMetadata(Component component) {
448 return convertMetadata(component, false, null);
451 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
452 Map<String, String> toscaMetadata = new LinkedHashMap<>();
453 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
454 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
456 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
457 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
458 List<CategoryDefinition> categories = component.getCategories();
459 CategoryDefinition categoryDefinition = categories.get(0);
460 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
462 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
463 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
464 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
465 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
466 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
467 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
468 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
469 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
470 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
471 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
472 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
473 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
474 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
476 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
479 switch (component.getComponentType()) {
481 Resource resource = (Resource) component;
482 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
483 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
484 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
486 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
488 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
489 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
490 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
491 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
494 Service service = (Service) component;
495 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
496 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
497 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
498 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
499 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
500 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
501 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
504 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
505 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
506 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
510 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
512 for (final String key : component.getCategorySpecificMetadata().keySet()) {
513 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
514 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
517 return toscaMetadata;
520 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
521 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
522 return INVARIANT_UUID;
524 return jsonPresentationField.getPresentation();
527 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
528 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
529 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
530 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
531 return Either.right(ToscaError.GENERAL_ERROR);
533 Map<String, Component> componentCache = new HashMap<>();
534 if (!ModelConverter.isAtomicComponent(component)) {
535 final List<Map<String, Map<String, String>>> additionalImports =
536 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
537 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
538 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
539 if (isNotEmpty(toscaArtifacts)) {
540 ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
541 if (artifactDefinition != null) {
542 Map<String, Map<String, String>> importsListMember = new HashMap<>();
543 Map<String, String> interfaceFiles = new HashMap<>();
544 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()));
545 StringBuilder keyNameBuilder = new StringBuilder();
546 keyNameBuilder.append(component.getComponentType().toString().toLowerCase()).append("-").append(component.getName())
547 .append("-interface");
548 importsListMember.put(keyNameBuilder.toString(), interfaceFiles);
549 additionalImports.add(importsListMember);
552 List<ComponentInstance> componentInstances = component.getComponentInstances();
553 if (componentInstances != null && !componentInstances.isEmpty()) {
554 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
556 toscaTemplate.setDependencies(dependencies);
557 toscaTemplate.setImports(additionalImports);
559 log.debug("currently imports supported for VF and service only");
561 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
564 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
565 return getConfiguration().getDefaultImports();
568 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
569 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
570 log.debug("createDependency componentCache {}", componentCache);
571 Component componentRI = componentCache.get(componentInstance.getComponentUid());
572 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
573 // all resource must be only once!
574 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
575 if ((resource.isRight()) && (log.isDebugEnabled())) {
576 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
577 componentInstance.getUniqueId());
580 final Component fetchedComponent = resource.left().value();
581 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
582 addDependencies(imports, dependencies, componentRI);
587 * Sets a componentCache from the given component/resource.
589 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
590 final Component fetchedComponent) {
591 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
592 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
593 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
594 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
595 .getToscaFullElement(componentInstance.getSourceModelUid());
596 if (sourceService.isRight() && (log.isDebugEnabled())) {
597 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
598 componentInstance.getUniqueId());
600 final Component fetchedSource = sourceService.left().value();
601 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
602 return fetchedSource;
604 return fetchedComponent;
608 * Retrieves all derived_from nodes and stores it in a predictable order.
610 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
611 final Component fetchedComponent) {
612 final Set<Component> componentsList = new LinkedHashSet<>();
613 if (fetchedComponent instanceof Resource) {
614 log.debug("fetchedComponent is a resource {}", fetchedComponent);
615 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
616 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
617 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
618 log.debug("Started entry.getValue() : {}", entry.getValue());
619 if (!NATIVE_ROOT.equals(entry.getValue())) {
620 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
621 if (resourcefetched != null && resourcefetched.isLeft()) {
622 componentsList.add(resourcefetched.left().value());
626 setImports(imports, dependencies, componentsList);
628 setImports(imports, dependencies, fetchedComponent);
634 * Returns all derived_from nodes found.
636 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
637 final Resource parentResource = (Resource) fetchedComponent;
638 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
639 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
640 componentsList.add(fetchedComponent);
641 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
642 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
643 .getToscaElement(componentInstance.getComponentUid());
644 if (resourcefetched != null && resourcefetched.isLeft()) {
645 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
646 if (MapUtils.isNotEmpty(derivedWithId)) {
647 derivedFromMapOfIdToName.putAll(derivedWithId);
652 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
654 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
655 return Optional.ofNullable(derivedFromMapOfIdToName);
659 * Creates a resource map and adds it to the import list.
661 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
662 final Set<Component> componentsList) {
663 componentsList.forEach(component -> setImports(imports, dependencies, component));
666 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
667 final Component component) {
668 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
669 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
670 if (artifactDefinition != null) {
671 final Map<String, String> files = new HashMap<>();
672 final String artifactName = artifactDefinition.getArtifactName();
673 files.put(IMPORTS_FILE_KEY, artifactName);
674 final StringBuilder keyNameBuilder = new StringBuilder();
675 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
676 keyNameBuilder.append("-");
677 keyNameBuilder.append(component.getName());
678 addImports(imports, keyNameBuilder, files);
679 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
680 if (!ModelConverter.isAtomicComponent(component)) {
681 final Map<String, String> interfaceFiles = new HashMap<>();
682 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
683 keyNameBuilder.append("-interface");
684 addImports(imports, keyNameBuilder, interfaceFiles);
690 * Adds the found resource to the import definition list.
692 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
693 final Map<String, String> files) {
694 final String mapKey = keyNameBuilder.toString();
695 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
696 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
697 importsListMember.put(keyNameBuilder.toString(), files);
698 imports.add(importsListMember);
702 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
703 Map<String, ToscaNodeType> nodeTypes) {
704 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
707 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
708 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
709 boolean isAssociatedComponent) {
710 log.debug("start convert node type for {}", component.getUniqueId());
711 ToscaNodeType toscaNodeType = createNodeType(component);
712 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
713 .getAllInterfaceLifecycleTypes(component.getModel());
714 if (lifecycleTypeEither.isRight()) {
715 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
716 return Either.right(ToscaError.GENERAL_ERROR);
718 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
719 .collect(Collectors.toList());
720 toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
721 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
722 if (dataTypesEither.isRight()) {
723 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
724 return Either.right(ToscaError.GENERAL_ERROR);
726 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
727 List<InputDefinition> inputDef = component.getInputs();
728 Map<String, ToscaProperty> mergedProperties = new HashMap<>();
729 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
730 addInputsToProperties(dataTypes, inputDef, mergedProperties);
731 final Map<String, ToscaAttribute> toscaAttributeMap;
732 toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
733 if (!toscaAttributeMap.isEmpty()) {
734 toscaNodeType.setAttributes(toscaAttributeMap);
736 if (CollectionUtils.isNotEmpty(component.getProperties())) {
737 List<PropertyDefinition> properties = component.getProperties();
738 Map<String, ToscaProperty> convertedProperties = properties.stream()
739 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
740 .toMap(PropertyDataDefinition::getName,
741 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
742 // merge component properties and inputs properties
743 mergedProperties.putAll(convertedProperties);
745 if (MapUtils.isNotEmpty(mergedProperties)) {
746 toscaNodeType.setProperties(mergedProperties);
748 /* convert private data_types */
749 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
750 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
751 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
752 for (DataTypeDefinition dataType : privateDataTypes) {
753 log.debug("Emitting private data type: component.name={} dataType.name={}",
754 component.getNormalizedName(), dataType.getName());
755 ToscaDataType toscaDataType = new ToscaDataType();
756 toscaDataType.setDerived_from(dataType.getDerivedFromName());
757 toscaDataType.setDescription(dataType.getDescription());
758 toscaDataType.setVersion(dataType.getVersion());
759 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
760 toscaDataType.setProperties(dataType.getProperties().stream()
761 .collect(Collectors.toMap(
762 PropertyDataDefinition::getName,
763 s -> propertyConvertor
764 .convertProperty(dataTypes, s, PropertyType.PROPERTY)
767 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
769 toscaNode.setData_types(toscaDataTypeMap);
772 // Extracted to method for code reuse
773 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
776 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
777 final Map<String, DataTypeDefinition> dataTypes) {
778 if (CollectionUtils.isEmpty(attributeList)) {
779 return Collections.emptyMap();
781 final AttributeConverter converter = new AttributeConverter(dataTypes);
782 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
783 for (final AttributeDefinition attributeDefinition : attributeList) {
784 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
786 return toscaAttributeMap;
789 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
790 Component component, ToscaTemplate toscaNode,
791 Map<String, ToscaNodeType> nodeTypes,
792 ToscaNodeType toscaNodeType,
793 Map<String, DataTypeDefinition> dataTypes) {
794 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
796 if (capabilities.isRight()) {
797 return Either.right(capabilities.right().value());
799 toscaNodeType = capabilities.left().value();
800 log.debug("Capabilities converted for {}", component.getUniqueId());
802 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
803 .convertRequirements(componentsCache, component, toscaNodeType);
804 if (requirements.isRight()) {
805 return Either.right(requirements.right().value());
807 toscaNodeType = requirements.left().value();
808 log.debug("Requirements converted for {}", component.getUniqueId());
810 String toscaResourceName;
811 switch (component.getComponentType()) {
813 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
814 .getMetadataDataDefinition()).getToscaResourceName();
817 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
818 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
821 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
822 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
825 nodeTypes.put(toscaResourceName, toscaNodeType);
826 toscaNode.setNode_types(nodeTypes);
827 log.debug("finish convert node type for {}", component.getUniqueId());
828 return Either.left(toscaNode);
831 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
832 final Map<String, Component> componentCache,
833 final Map<String, DataTypeDefinition> dataTypes,
834 final ToscaTopolgyTemplate topologyTemplate) {
836 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
837 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
838 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
839 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
840 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
842 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
843 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
844 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
846 Map<String, ToscaGroupTemplate> groupsMap = null;
847 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
848 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
849 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
850 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
852 nodeTemplate.setType(componentInstance.getToscaComponentName());
853 nodeTemplate.setDirectives(componentInstance.getDirectives());
854 nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
856 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
857 .getOriginComponent(componentCache, componentInstance);
858 if (originComponentRes.isRight()) {
859 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
862 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
863 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
864 if (requirements.isRight()) {
865 convertNodeTemplatesRes = Either.right(requirements.right().value());
868 final String instanceUniqueId = componentInstance.getUniqueId();
869 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
871 nodeTemplate = requirements.left().value();
873 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
875 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
876 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
877 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
879 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
882 final Either<ToscaNodeTemplate, ToscaError> capabilities =
883 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
884 if (capabilities.isRight()) {
885 convertNodeTemplatesRes = Either.right(capabilities.right().value());
888 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
890 nodeTemplate = capabilities.left().value();
891 final Map<String, Object> props = new HashMap<>();
892 final Map<String, Object> attribs = new HashMap<>();
894 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
895 // Adds the properties of parent component to map
896 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
897 addAttributesOfParentComponent(originalComponent, attribs);
900 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
901 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
903 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
904 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
907 if (componentInstancesInputs != null
908 && componentInstancesInputs.containsKey(instanceUniqueId)
909 && !isComponentOfTypeServiceProxy(componentInstance)) {
910 //For service proxy the inputs are already handled under instance properties above
911 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
914 //M3[00001] - NODE TEMPLATE INTERFACES - START
915 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
916 //M3[00001] - NODE TEMPLATE INTERFACES - END
917 if (MapUtils.isNotEmpty(props)) {
918 nodeTemplate.setProperties(props);
920 if (MapUtils.isNotEmpty(attribs)) {
921 nodeTemplate.setAttributes(attribs);
924 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
925 if (CollectionUtils.isNotEmpty(groupInstances)) {
926 if (groupsMap == null) {
927 groupsMap = new HashMap<>();
929 for (final GroupInstance groupInst : groupInstances) {
930 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
931 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
936 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
938 if (groupsMap != null) {
939 log.debug("instance groups added");
940 topologyTemplate.addGroups(groupsMap);
942 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
943 ((Service) component).getForwardingPaths())) {
944 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
945 ForwardingPathToscaUtil
946 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
947 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
949 if (convertNodeTemplatesRes == null) {
950 convertNodeTemplatesRes = Either.left(nodeTemplates);
952 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
953 return convertNodeTemplatesRes;
956 private void handleInstanceInterfaces(
957 Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
958 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
959 String instanceUniqueId,
960 Component parentComponent) {
962 if (MapUtils.isEmpty(componentInstanceInterfaces)
963 || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
964 nodeTemplate.setInterfaces(null);
968 final List<ComponentInstanceInterface> currServiceInterfaces =
969 componentInstanceInterfaces.get(instanceUniqueId);
971 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
972 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
973 .getUniqueId(), instInterface));
975 final Map<String, Object> interfaceMap = interfacesOperationsConverter
976 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance),
977 isComponentOfTypeServiceProxy(componentInstance));
979 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
980 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
983 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
984 return Objects.nonNull(componentInstance.getOriginType())
985 && componentInstance.getOriginType().getValue().equals("Service Proxy");
988 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
989 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
990 String instanceUniqueId, Map<String, Object> props) {
992 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
993 if (instanceInputsList != null) {
994 instanceInputsList.forEach(input -> {
995 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue();
996 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1001 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1002 final Map<String, DataTypeDefinition> dataTypes,
1003 final String instanceUniqueId,
1004 final Map<String, Object> props) {
1006 if (isNotEmpty(componentInstancesProperties)) {
1007 componentInstancesProperties.get(instanceUniqueId)
1008 // Converts and adds each value to property map
1009 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1013 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1014 final String instanceUniqueId,
1015 final Map<String, Object> attribs) {
1017 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1018 componentInstancesAttributes.get(instanceUniqueId).stream()
1019 // Filters out Attributes with empty default values
1020 .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue()))
1021 // Converts and adds each value to attribute map
1022 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1026 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1027 Component componentOfInstance, Map<String, Object> props) {
1029 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1030 if (isNotEmpty(componentProperties)) {
1031 componentProperties.stream()
1032 // Filters out properties with empty default values
1033 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1034 // Converts and adds each value to property map
1035 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1039 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1041 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1042 if (isNotEmpty(componentAttributes)) {
1043 componentAttributes.stream()
1044 // Filters out Attributes with empty default values
1045 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1046 // Converts and adds each value to attribute map
1047 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1051 private ToscaNodeType createNodeType(Component component) {
1052 ToscaNodeType toscaNodeType = new ToscaNodeType();
1053 if (ModelConverter.isAtomicComponent(component)) {
1054 if (((Resource) component).getDerivedFrom() != null) {
1055 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1057 toscaNodeType.setDescription(component.getDescription());
1059 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1061 toscaNodeType.setDerived_from(derivedFrom);
1063 return toscaNodeType;
1066 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1068 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1069 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1070 List<ComponentInstance> componentInstances = container.getComponentInstances();
1071 if (CollectionUtils.isEmpty(componentInstances)) {
1074 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1075 componentInstances.stream()
1076 .filter(this::isComponentOfTypeServiceProxy)
1077 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1078 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1081 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1082 Component serviceComponent;
1083 ComponentParametersView componentParametersView = new ComponentParametersView();
1084 componentParametersView.disableAll();
1085 componentParametersView.setIgnoreInterfaces(false);
1086 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1087 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1088 if (service.isRight()) {
1089 log.debug("Failed to fetch original service component with id {} for instance {}",
1090 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1091 return Either.right(ToscaError.GENERAL_ERROR);
1093 serviceComponent = service.left().value();
1096 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1097 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1098 if (lifecycleTypeEither.isRight()) {
1099 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1100 return Either.right(ToscaError.GENERAL_ERROR);
1103 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1104 .map(InterfaceDataDefinition::getType)
1105 .collect(Collectors.toList());
1106 //Add interface types for local interfaces in the original service component for proxy
1107 Map<String, Object> localInterfaceTypes = addInterfaceTypeElement(serviceComponent,
1108 allGlobalInterfaceTypes);
1109 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1110 proxyInterfaceTypes.putAll(localInterfaceTypes);
1114 return Either.left(proxyInterfaceTypes);
1117 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1118 Component container) {
1120 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1121 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1123 List<ComponentInstance> componentInstances = container.getComponentInstances();
1125 if (componentInstances == null || componentInstances.isEmpty()) {
1128 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1129 List<ComponentInstance> proxyInst = componentInstances.stream()
1130 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1131 .collect(Collectors.toList());
1132 if (proxyInst != null && !proxyInst.isEmpty()) {
1133 for (ComponentInstance inst : proxyInst) {
1134 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1138 if (serviceProxyInstanceList.isEmpty()) {
1141 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1142 .getLatestByName("serviceProxy", null);
1143 if (serviceProxyOrigin.isRight()) {
1144 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1145 serviceProxyOrigin.right().value());
1146 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1148 Component origComponent = serviceProxyOrigin.left().value();
1150 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1151 Component serviceComponent = null;
1152 ComponentParametersView componentParametersView = new ComponentParametersView();
1153 componentParametersView.disableAll();
1154 componentParametersView.setIgnoreCategories(false);
1155 componentParametersView.setIgnoreProperties(false);
1156 componentParametersView.setIgnoreInputs(false);
1157 componentParametersView.setIgnoreInterfaces(false);
1158 componentParametersView.setIgnoreRequirements(false);
1159 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1160 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1161 if (service.isRight()) {
1162 log.debug("Failed to fetch resource with id {} for instance {}",
1163 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1165 serviceComponent = service.left().value();
1168 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1169 entryProxy.getValue());
1170 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1173 return Either.left(nodeTypesMap);
1176 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1177 final Component container, final ToscaTemplate toscaNode) {
1178 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1180 if (CollectionUtils.isEmpty(componentInstances)) {
1183 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1184 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1185 .collect(Collectors.toList());
1186 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1187 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1188 final Map<String, ToscaNodeType> nodeTypes =
1189 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1190 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1196 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1197 Component proxyComponent, ComponentInstance componentInstance) {
1198 ToscaNodeType toscaNodeType = new ToscaNodeType();
1199 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1201 toscaNodeType.setDerived_from(derivedFrom);
1202 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel());
1203 if (dataTypesEither.isRight()) {
1204 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1206 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1207 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1208 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1210 if (MapUtils.isNotEmpty(capabilities)) {
1211 toscaNodeType.setCapabilities(capabilities);
1213 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1214 .convertProxyRequirements(componentCache, componentInstance);
1215 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1216 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1218 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1219 proxyProperties.ifPresent(toscaNodeType::setProperties);
1221 Map<String, Object> interfaceMap = new HashMap<>();
1222 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1223 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1224 if (proxyInterfaces.isPresent()) {
1225 interfaceMap = proxyInterfaces.get();
1228 interfaceMap = interfacesOperationsConverter
1229 .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false);
1232 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1233 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1235 return toscaNodeType;
1238 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1239 ComponentInstance componentInstance,
1240 List<RequirementCapabilityRelDef> relations,
1241 ToscaNodeTemplate nodeTypeTemplate,
1242 Component originComponent,
1243 Map<String, Component> componentCache) {
1245 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1247 if (isNotEmpty(requirementDefinitionList)) {
1249 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache);
1250 if (!toscaRequirements.isEmpty()) {
1251 nodeTypeTemplate.setRequirements(toscaRequirements);
1253 } catch (final Exception e) {
1254 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1255 componentInstance.getName(), e);
1256 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1259 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1260 return Either.left(nodeTypeTemplate);
1263 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1264 final ComponentInstance componentInstance,
1265 final List<RequirementCapabilityRelDef> filteredRelations,
1266 final Component originComponent,
1267 final Map<String, Component> componentCache)
1268 throws ToscaExportException {
1270 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1271 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1272 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1273 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1274 toscaRequirements.add(toscaTemplateRequirementMap);
1277 return toscaRequirements;
1280 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1281 List<RequirementCapabilityRelDef> relations) {
1282 return relations.stream()
1283 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1286 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1287 final Component fromOriginComponent,
1288 final List<ComponentInstance> instancesList,
1289 final RequirementCapabilityRelDef relationshipDefinition,
1290 final Map<String, Component> componentCache)
1291 throws ToscaExportException {
1293 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1294 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1295 .getRelationships().get(0);
1296 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1298 final ComponentInstance toInstance = instancesList.stream()
1299 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1300 .findFirst().orElse(null);
1301 if (toInstance == null) {
1302 final String errorMsg = String
1303 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1304 relationshipDefinition.getToNode());
1305 log.debug(errorMsg);
1306 throw new ToscaExportException(errorMsg);
1308 final Optional<RequirementDefinition> reqOpt =
1309 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1310 if (reqOpt.isEmpty()) {
1311 final String errorMsg = String
1312 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1313 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1314 log.debug(errorMsg);
1315 throw new ToscaExportException(errorMsg);
1317 final ComponentParametersView filter = new ComponentParametersView(true);
1318 filter.setIgnoreComponentInstances(false);
1319 filter.setIgnoreCapabilities(false);
1320 filter.setIgnoreGroups(false);
1321 final Either<Component, StorageOperationStatus> getOriginRes =
1322 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1323 if (getOriginRes.isRight()) {
1324 final String errorMsg = String.format(
1325 "Failed to build substituted name for the requirement %s. "
1326 + "Failed to get an origin component with uniqueId %s",
1327 reqOpt.get().getName(), toInstance.getActualComponentUid());
1328 log.debug(errorMsg);
1329 throw new ToscaExportException(errorMsg);
1331 final Component toOriginComponent = getOriginRes.left().value();
1332 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1333 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1334 if (capOpt.isEmpty()) {
1335 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1336 if (capOpt.isEmpty()) {
1337 final String errorMsg = String
1338 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1339 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1340 log.debug(errorMsg);
1341 throw new ToscaExportException(errorMsg);
1344 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1345 capabilityRequirementRelationship, toInstance, componentCache);
1348 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1349 CapabilityDefinition capability) {
1350 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1351 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1354 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1355 Component toOriginComponent, Component fromOriginComponent,
1356 RequirementDefinition requirement) {
1357 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1358 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1359 if (!cap.isPresent()) {
1360 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1361 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1366 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1367 final Component toOriginComponent,
1368 final CapabilityDefinition capability,
1369 final RequirementDefinition requirement,
1370 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1371 final ComponentInstance toInstance,
1372 final Map<String, Component> componentCache)
1373 throws ToscaExportException {
1375 List<String> reducedPath = capability.getPath();
1376 if (capability.getOwnerId() != null) {
1377 reducedPath = capabilityRequirementConverter
1378 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1380 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1381 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1382 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName());
1383 if (capabilityNameEither.isRight()) {
1384 final String errorMsg = String.format(
1385 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1386 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1389 throw new ToscaExportException(errorMsg);
1391 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1392 .buildSubstitutedName(componentCache, fromOriginComponent,
1393 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName());
1394 if (requirementNameEither.isRight()) {
1395 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1396 + "with name %s on a component with uniqueId %s",
1397 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1398 log.debug(errorMsg);
1399 throw new ToscaExportException(errorMsg);
1401 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1402 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1403 toscaRequirement.setNode(toInstance.getName());
1404 toscaRequirement.setCapability(capabilityNameEither.left().value());
1405 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1406 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1408 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1412 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1413 Map<String, List<RequirementDefinition>> reqMap,
1414 RelationshipInfo reqAndRelationshipPair,
1415 String fromInstanceId) {
1416 for (List<RequirementDefinition> reqList : reqMap.values()) {
1417 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1418 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1420 if (reqOpt.isPresent()) {
1424 return Optional.empty();
1428 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1429 * 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
1430 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1432 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1433 RequirementDefinition requirement, String fromInstanceId) {
1434 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1435 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1436 reqAndRelationshipPair.getRequirement());
1439 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1443 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1444 Component originComponent) {
1445 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1446 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1447 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1450 private boolean isCvfc(Component component) {
1451 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1454 private Either<SubstitutionMapping, ToscaError> convertCapabilities(Component component, SubstitutionMapping substitutionMappings,
1455 Map<String, Component> componentCache) {
1456 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
1457 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes = capabilityRequirementConverter
1458 .convertSubstitutionMappingCapabilities(componentCache, component);
1459 if (toscaCapabilitiesRes.isRight()) {
1460 result = Either.right(toscaCapabilitiesRes.right().value());
1461 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1462 } else if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1463 substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value());
1464 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1466 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1470 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1471 Map<String, DataTypeDefinition> dataTypes) {
1472 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1473 if (!toscaCapabilities.isEmpty()) {
1474 nodeType.setCapabilities(toscaCapabilities);
1476 log.debug("Finish convert Capabilities for node type");
1477 return Either.left(nodeType);
1480 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1481 if (artifacts == null) {
1484 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1485 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1486 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1487 artifact.setFile(entry.getValue().getFile());
1488 artifact.setType(entry.getValue().getType());
1489 arts.put(entry.getKey(), artifact);
1494 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1495 if (inNodeFilter == null) {
1498 NodeFilter nodeFilter = new NodeFilter();
1499 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1500 ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties();
1501 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1502 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1503 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1504 copyNodeFilterProperties(origProperties, propertiesCopy);
1505 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1506 nodeFilter.setCapabilities(capabilitiesCopy);
1508 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1509 nodeFilter.setProperties(propertiesCopy);
1511 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1512 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1516 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1517 if (substitutionFilterDataDefinition == null) {
1520 NodeFilter nodeFilter = new NodeFilter();
1521 ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties();
1522 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1523 copySubstitutionFilterProperties(origProperties, propertiesCopy);
1524 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1525 nodeFilter.setProperties(propertiesCopy);
1527 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1528 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1531 private Object cloneToscaId(Object toscaId) {
1532 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1535 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1536 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1537 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1540 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1541 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1542 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1546 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1547 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1548 CapabilityFilter capabilityFilter = new CapabilityFilter();
1549 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1550 copyNodeFilterProperties(capability.getProperties(), propertiesCopy);
1551 capabilityFilter.setProperties(propertiesCopy);
1552 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1553 capabilitiesCopy.add(capabilityFilterCopyMap);
1557 private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties,
1558 List<Map<String, List<Object>>> propertiesCopy) {
1559 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1562 Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1563 for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1564 for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1565 Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1566 String propertyName = propertyDataDefinition.getName();
1567 if (propertyMapCopy.containsKey(propertyName)) {
1568 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1570 if (propertyName != null) {
1571 List<Object> propsList = new ArrayList<>();
1572 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1573 propertyMapCopy.put(propertyName, propsList);
1575 propertyMapCopy.putAll(propertyValObj);
1580 propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1583 private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties,
1584 final List<Map<String, List<Object>>> propertiesCopy) {
1585 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1588 final Map<String, List<Object>> propertyMapCopy = new HashMap<>();
1589 for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) {
1590 for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) {
1591 final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class);
1592 final String propertyName = propertyDataDefinition.getName();
1593 if (propertyMapCopy.containsKey(propertyName)) {
1594 addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName));
1596 if (propertyName != null) {
1597 final List<Object> propsList = new ArrayList<>();
1598 addPropertyConstraintValueToList(propertyName, propertyValObj, propsList);
1599 propertyMapCopy.put(propertyName, propsList);
1601 propertyMapCopy.putAll(propertyValObj);
1606 propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry));
1609 private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) {
1610 if (propertyValObj.containsKey(propertyName)) {
1611 propsList.add(propertyValObj.get(propertyName));
1613 propsList.add(propertyValObj);
1617 private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) {
1618 Map<String, List<Object>> tempMap = new HashMap<>();
1619 tempMap.put(entry.getKey(), entry.getValue());
1620 propertiesCopy.add(tempMap);
1623 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1624 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1625 return Collections.emptyMap();
1627 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1628 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1631 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1632 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1633 return Collections.emptyMap();
1635 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1636 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1639 Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1640 if (Objects.isNull(proxyComponent)) {
1641 return Optional.empty();
1643 Map<String, ToscaProperty> proxyProperties = new HashMap<>();
1644 addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties);
1645 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1646 proxyProperties.putAll(proxyComponent.getProperties().stream()
1647 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1648 .toMap(PropertyDataDefinition::getName,
1649 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))));
1651 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1654 void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1655 Map<String, ToscaProperty> mergedProperties) {
1656 if (CollectionUtils.isEmpty(componentInputs)) {
1659 for (InputDefinition input : componentInputs) {
1660 ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
1661 mergedProperties.put(input.getName(), property);
1665 Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1666 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1667 return Optional.empty();
1669 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1670 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1672 // always available in the proxy node template
1673 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1675 .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false));
1678 private static class CustomRepresenter extends Representer {
1680 CustomRepresenter() {
1682 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1683 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1684 // null representer is exceptional and it is stored as an instance
1687 this.nullRepresenter = new RepresentNull();
1690 public boolean validateGetInputValue(final Object valueObj) {
1691 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1694 if (valueObj instanceof List) {
1695 return ((List) valueObj).size() > 1;
1700 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1701 if (valueObj instanceof List) {
1702 return ((List) valueObj).size() > 1;
1708 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1709 if (propertyValue == null) {
1712 // skip not relevant for Tosca property
1713 if ("dependencies".equals(property.getName())) {
1716 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1719 removeDefaultP(propertyValue);
1720 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1721 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1722 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1724 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1727 private void removeDefaultP(final Object propertyValue) {
1728 if (propertyValue instanceof Map) {
1729 final Map mapPropertyValue = ((Map) propertyValue);
1730 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1731 Object defaultValue = null;
1732 while (iter.hasNext()) {
1733 final Map.Entry entry = iter.next();
1734 if ("_defaultp_".equals(entry.getKey())) {
1735 defaultValue = entry.getValue();
1737 } else if (entry.getValue() instanceof Map) {
1738 removeDefaultP(entry.getValue());
1741 if (defaultValue != null) {
1742 mapPropertyValue.putIfAbsent("default", defaultValue);
1748 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1749 // remove the bean type from the output yaml (!! ...)
1750 if (!classTags.containsKey(javaBean.getClass())) {
1751 addClassTag(javaBean.getClass(), Tag.MAP);
1753 return super.representJavaBean(properties, javaBean);
1756 private class RepresentToscaAttribute implements Represent {
1759 public Node representData(Object data) {
1760 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1761 return represent(toscaAttribute.asToscaMap());
1765 private class RepresentToscaPropertyAssignment implements Represent {
1767 public Node representData(Object data) {
1768 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1769 if (toscaOperationAssignment.getValue() instanceof String) {
1770 final String stringValue = (String) toscaOperationAssignment.getValue();
1771 if (isPropertyOrAttributeFunction(stringValue)) {
1772 return representGetAttribute(stringValue);
1774 return representScalar(Tag.STR, stringValue);
1776 return represent(null);
1779 public Node representGetAttribute(final String getAttributeFunction) {
1780 return represent(new Yaml().load(getAttributeFunction));
1783 public boolean isPropertyOrAttributeFunction(final String value) {
1785 final Yaml yaml = new Yaml();
1786 final Object yamlObj = yaml.load(value);
1787 if (!(yamlObj instanceof Map)) {
1790 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1791 if (getAttributeMap.size() != 1) {
1794 final List<String> functionList = Arrays
1795 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1796 final Optional<String> function = getAttributeMap.keySet().stream()
1797 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1798 if (function.isEmpty()) {
1801 final String functionName = function.get();
1802 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1803 if (GET_INPUT.getFunctionName().equals(functionName)) {
1804 return validateGetInputValue(getAttributeValueObj);
1806 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1808 } catch (final Exception ignored) {
1814 private class RepresentNull implements Represent {
1817 public Node representData(Object data) {
1818 // possible values are here http://yaml.org/type/null.html
1819 return representScalar(Tag.NULL, "");
1824 private static class UnsortedPropertyUtils extends PropertyUtils {
1827 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1828 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1829 return new LinkedHashSet<>(fields);
1833 private Configuration getConfiguration() {
1834 return ConfigurationManager.getConfigurationManager().getConfiguration();