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.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
26 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
27 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
29 import com.fasterxml.jackson.databind.ObjectMapper;
30 import com.google.common.primitives.Ints;
31 import com.google.gson.JsonElement;
32 import com.google.gson.JsonObject;
33 import com.google.gson.JsonParser;
34 import com.google.gson.stream.JsonReader;
35 import fj.data.Either;
36 import java.io.StringReader;
37 import java.nio.file.Path;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.LinkedHashMap;
46 import java.util.LinkedHashSet;
47 import java.util.List;
49 import java.util.Map.Entry;
50 import java.util.Objects;
51 import java.util.Optional;
53 import java.util.function.Supplier;
54 import java.util.stream.Collectors;
55 import org.apache.commons.collections.CollectionUtils;
56 import org.apache.commons.collections.MapUtils;
57 import org.apache.commons.io.FilenameUtils;
58 import org.apache.commons.lang3.StringUtils;
59 import org.apache.commons.lang3.tuple.ImmutablePair;
60 import org.apache.commons.lang3.tuple.ImmutableTriple;
61 import org.apache.commons.lang3.tuple.Triple;
62 import org.onap.sdc.tosca.services.YamlUtil;
63 import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException;
64 import org.openecomp.sdc.be.config.Configuration;
65 import org.openecomp.sdc.be.config.ConfigurationManager;
66 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
67 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
68 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
69 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
70 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
71 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
72 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
73 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
74 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
75 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
76 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
77 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
78 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition;
79 import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
81 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
82 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
83 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
84 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
85 import org.openecomp.sdc.be.exception.ToscaExportException;
86 import org.openecomp.sdc.be.model.ArtifactDefinition;
87 import org.openecomp.sdc.be.model.AttributeDefinition;
88 import org.openecomp.sdc.be.model.CapabilityDefinition;
89 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
90 import org.openecomp.sdc.be.model.Component;
91 import org.openecomp.sdc.be.model.ComponentInstance;
92 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
93 import org.openecomp.sdc.be.model.ComponentInstanceInput;
94 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
95 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
96 import org.openecomp.sdc.be.model.ComponentParametersView;
97 import org.openecomp.sdc.be.model.DataTypeDefinition;
98 import org.openecomp.sdc.be.model.GroupInstance;
99 import org.openecomp.sdc.be.model.InputDefinition;
100 import org.openecomp.sdc.be.model.InterfaceDefinition;
101 import org.openecomp.sdc.be.model.PropertyDefinition;
102 import org.openecomp.sdc.be.model.RelationshipInfo;
103 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
104 import org.openecomp.sdc.be.model.RequirementDefinition;
105 import org.openecomp.sdc.be.model.Resource;
106 import org.openecomp.sdc.be.model.Service;
107 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
108 import org.openecomp.sdc.be.model.category.CategoryDefinition;
109 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
110 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
111 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
112 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
113 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
114 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
115 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
116 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
117 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
118 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
119 import org.openecomp.sdc.be.tosca.model.NodeFilter;
120 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
121 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
122 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
123 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
124 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
125 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
126 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
127 import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
128 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
129 import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment;
130 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
131 import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate;
132 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
133 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
134 import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact;
135 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
136 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
137 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
138 import org.openecomp.sdc.be.tosca.utils.InputConverter;
139 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
140 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
141 import org.openecomp.sdc.common.log.wrappers.Logger;
142 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
143 import org.springframework.beans.factory.annotation.Autowired;
144 import org.yaml.snakeyaml.DumperOptions;
145 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
146 import org.yaml.snakeyaml.Yaml;
147 import org.yaml.snakeyaml.introspector.BeanAccess;
148 import org.yaml.snakeyaml.introspector.Property;
149 import org.yaml.snakeyaml.introspector.PropertyUtils;
150 import org.yaml.snakeyaml.nodes.MappingNode;
151 import org.yaml.snakeyaml.nodes.Node;
152 import org.yaml.snakeyaml.nodes.NodeTuple;
153 import org.yaml.snakeyaml.nodes.Tag;
154 import org.yaml.snakeyaml.representer.Represent;
155 import org.yaml.snakeyaml.representer.Representer;
157 @org.springframework.stereotype.Component("tosca-export-handler")
158 public class ToscaExportHandler {
160 public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate";
161 private static final Logger log = Logger.getLogger(ToscaExportHandler.class);
162 private static final String INVARIANT_UUID = "invariantUUID";
163 private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3";
164 private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service.";
165 private static final String IMPORTS_FILE_KEY = "file";
166 private static final String TOSCA_INTERFACE_NAME = "-interface.yml";
167 private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration";
168 private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
169 private static final String NATIVE_ROOT = "tosca.nodes.Root";
170 private static final List<String> EXCLUDED_CATEGORY_SPECIFIC_METADATA = List
171 .of("Service Function", "Service Role", "Naming Policy", "Service Type");
172 private static final YamlUtil yamlUtil = new YamlUtil();
173 private final ApplicationDataTypeCache applicationDataTypeCache;
174 private final ToscaOperationFacade toscaOperationFacade;
175 private final CapabilityRequirementConverter capabilityRequirementConverter;
176 private final PolicyExportParser policyExportParser;
177 private final GroupExportParser groupExportParser;
178 private final PropertyConvertor propertyConvertor;
179 private final AttributeConverter attributeConverter;
180 private final InputConverter inputConverter;
181 private final OutputConverter outputConverter;
182 private final InterfaceLifecycleOperation interfaceLifecycleOperation;
183 private final InterfacesOperationsConverter interfacesOperationsConverter;
184 private final ModelOperation modelOperation;
187 public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache,
188 final ToscaOperationFacade toscaOperationFacade,
189 final CapabilityRequirementConverter capabilityRequirementConverter,
190 final PolicyExportParser policyExportParser,
191 final GroupExportParser groupExportParser,
192 final PropertyConvertor propertyConvertor,
193 final AttributeConverter attributeConverter,
194 final InputConverter inputConverter,
195 final OutputConverter outputConverter,
196 final InterfaceLifecycleOperation interfaceLifecycleOperation,
197 final InterfacesOperationsConverter interfacesOperationsConverter,
198 final ModelOperation modelOperation) {
199 this.applicationDataTypeCache = applicationDataTypeCache;
200 this.toscaOperationFacade = toscaOperationFacade;
201 this.capabilityRequirementConverter = capabilityRequirementConverter;
202 this.policyExportParser = policyExportParser;
203 this.groupExportParser = groupExportParser;
204 this.propertyConvertor = propertyConvertor;
205 this.attributeConverter = attributeConverter;
206 this.inputConverter = inputConverter;
207 this.outputConverter = outputConverter;
208 this.interfaceLifecycleOperation = interfaceLifecycleOperation;
209 this.interfacesOperationsConverter = interfacesOperationsConverter;
210 this.modelOperation = modelOperation;
213 public static String getInterfaceFilename(String artifactName) {
214 return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME;
217 private static void removeOperationImplementationForProxyNodeType(Map<String, InterfaceDefinition> proxyComponentInterfaces) {
218 if (MapUtils.isEmpty(proxyComponentInterfaces)) {
221 proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty)
222 .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null)));
225 public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
226 return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
229 public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
230 return convertDataTypeToToscaTemplate(dataTypeDefinition).left().map(this::createToscaRepresentation);
233 public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
234 final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
235 if (CollectionUtils.isEmpty(imports)) {
236 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
237 return Either.right(ToscaError.GENERAL_ERROR);
239 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
240 if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
241 .startsWith("org.openecomp.resource.abstract.nodes.")) {
242 final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
243 .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
244 component.getModel());
245 if (baseType.isLeft() && baseType.left().value() != null) {
246 addDependencies(imports, dependencies, baseType.left().value());
248 log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
252 String toscaVersion = null;
253 if (component instanceof Resource) {
254 toscaVersion = ((Resource) component).getToscaVersion();
256 ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
257 toscaTemplate.setImports(imports);
258 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
259 final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
260 isAssociatedComponent);
261 if (toscaTemplateRes.isRight()) {
262 return Either.right(toscaTemplateRes.right().value());
264 toscaTemplate = toscaTemplateRes.left().value();
265 toscaTemplate.setDependencies(dependencies);
266 ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
267 return Either.left(toscaRepresentation);
270 private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
271 CustomRepresenter representer = new CustomRepresenter();
272 DumperOptions options = new DumperOptions();
273 options.setAllowReadOnlyProperties(false);
274 options.setPrettyFlow(true);
275 options.setDefaultFlowStyle(FlowStyle.FLOW);
276 options.setCanonical(false);
277 representer.addClassTag(toscaTemplate.getClass(), Tag.MAP);
278 representer.setPropertyUtils(new UnsortedPropertyUtils());
281 Yaml yaml = new Yaml(representer, options);
282 String yamlAsString = yaml.dumpAsMap(toscaTemplate);
283 StringBuilder sb = new StringBuilder();
284 sb.append(getConfiguration().getHeatEnvArtifactHeader());
285 sb.append(yamlAsString);
286 sb.append(getConfiguration().getHeatEnvArtifactFooter());
287 return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate);
290 public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
291 ToscaTemplate toscaTemplate = new ToscaTemplate(null);
292 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
293 if (fillImports.isRight()) {
294 return Either.right(fillImports.right().value());
296 return Either.left(fillImports.left().value().left);
299 public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
300 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
301 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
302 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
303 return Either.right(ToscaError.GENERAL_ERROR);
305 log.trace("start tosca export for {}", component.getUniqueId());
306 String toscaVersion = null;
307 if (component instanceof Resource) {
308 toscaVersion = ((Resource) component).getToscaVersion();
310 final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
311 toscaTemplate.setMetadata(convertMetadata(component));
312 toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
313 final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
314 if (ModelConverter.isAtomicComponent(component)) {
315 log.trace("convert component as node type");
316 return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
318 log.trace("convert component as topology template");
319 return convertToscaTemplate(component, toscaTemplate);
323 private Either<ToscaTemplate, ToscaError> convertDataTypeToToscaTemplate(final DataTypeDefinition dataTypeDefinition) {
324 final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
325 return convertDataTypeTosca(dataTypeDefinition, toscaTemplate);
328 private Either<ToscaTemplate, ToscaError> convertDataTypeTosca(final DataTypeDefinition dataTypeDefinition, final ToscaTemplate toscaTemplate) {
329 final var dataTypesEither = applicationDataTypeCache.getAll(dataTypeDefinition.getModel());
330 if (dataTypesEither.isRight()) {
331 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
332 return Either.right(ToscaError.GENERAL_ERROR);
334 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
335 if (!dataTypeDefinition.isEmpty()) {
336 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
337 ToscaDataType toscaDataType = new ToscaDataType();
338 toscaDataType.setDerived_from(dataTypeDefinition.getDerivedFromName());
339 toscaDataType.setDescription(dataTypeDefinition.getDescription());
340 toscaDataType.setVersion(dataTypeDefinition.getVersion());
341 if (CollectionUtils.isNotEmpty(dataTypeDefinition.getProperties())) {
342 toscaDataType.setProperties(dataTypeDefinition.getProperties().stream()
343 .collect(Collectors.toMap(
344 PropertyDataDefinition::getName,
345 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
346 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty((List<DataTypeDefinition>) dataTypeDefinition, toscaPropertyTobeValidated,
350 toscaDataTypeMap.put(dataTypeDefinition.getName(), toscaDataType);
351 toscaTemplate.setData_types(toscaDataTypeMap);
353 return Either.left(toscaTemplate);
356 private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
357 if (modelId == null) {
358 return getDefaultToscaImportConfig();
361 final List<ToscaImportByModel> allModelImports = modelOperation.findAllModelImports(modelId, true);
362 final List<Map<String, Map<String, String>>> importList = new ArrayList<>();
363 final Set<Path> addedPathList = new HashSet<>();
364 for (final ToscaImportByModel toscaImportByModel : allModelImports) {
365 var importPath = Path.of(toscaImportByModel.getFullPath());
366 if (addedPathList.contains(importPath)) {
367 importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
369 final String fileName = FilenameUtils.getBaseName(importPath.toString());
370 importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
371 addedPathList.add(importPath);
376 private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
377 Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
378 if (importsRes.isRight()) {
379 return Either.right(importsRes.right().value());
381 toscaNode = importsRes.left().value().left;
382 Map<String, Component> componentCache = importsRes.left().value().right;
383 Either<Map<String, ToscaNodeType>, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component);
384 if (nodeTypesMapEither.isRight()) {
385 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value());
386 return Either.right(nodeTypesMapEither.right().value());
388 Map<String, ToscaNodeType> nodeTypesMap = nodeTypesMapEither.left().value();
389 if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) {
390 toscaNode.setNode_types(nodeTypesMap);
392 createServiceSubstitutionNodeTypes(componentCache, component, toscaNode);
393 Either<Map<String, Object>, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component);
394 if (proxyInterfaceTypesEither.isRight()) {
395 log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value());
396 return Either.right(proxyInterfaceTypesEither.right().value());
398 Map<String, Object> proxyInterfaceTypes = proxyInterfaceTypesEither.left().value();
399 if (MapUtils.isNotEmpty(proxyInterfaceTypes)) {
400 toscaNode.setInterface_types(proxyInterfaceTypes);
402 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
403 if (dataTypesEither.isRight()) {
404 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
405 return Either.right(ToscaError.GENERAL_ERROR);
407 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
408 ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
409 List<InputDefinition> inputDef = component.getInputs();
410 Map<String, ToscaProperty> inputs = inputConverter.convertInputs(inputDef, dataTypes);
411 if (!inputs.isEmpty()) {
412 topologyTemplate.setInputs(inputs);
414 final Map<String, ToscaProperty> outputs;
416 outputs = outputConverter.convert(component.getOutputs(), dataTypes);
417 } catch (final ToscaConversionException e) {
418 log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
419 "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e);
420 return Either.right(ToscaError.GENERAL_ERROR);
422 if (!outputs.isEmpty()) {
423 topologyTemplate.setOutputs(outputs);
425 if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
426 final Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
427 convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate);
428 if (nodeTemplates.isRight()) {
429 return Either.right(nodeTemplates.right().value());
431 log.debug("node templates converted");
432 topologyTemplate.setNode_templates(nodeTemplates.left().value());
434 final Map<String, ToscaRelationshipTemplate> relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler()
435 .createFrom(topologyTemplate.getNode_templates());
436 if (!relationshipTemplatesMap.isEmpty()) {
437 topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap);
439 addGroupsToTopologyTemplate(component, topologyTemplate);
441 addPoliciesToTopologyTemplate(component, topologyTemplate);
442 } catch (SdcResourceNotFoundException e) {
443 log.debug("Fail to add policies to topology template:", e);
444 return Either.right(ToscaError.GENERAL_ERROR);
447 createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings);
448 } catch (final ToscaExportException e) {
449 log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage());
450 return Either.right(e.getToscaError());
452 if (!topologyTemplate.isEmpty()) {
453 toscaNode.setTopology_template(topologyTemplate);
455 return Either.left(toscaNode);
458 private Either<String, ToscaError> createComponentToscaName(final Component component) {
459 switch (component.getComponentType()) {
461 final ResourceMetadataDataDefinition resourceMetadata =
462 (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition();
463 return Either.left(resourceMetadata.getToscaResourceName());
465 return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName());
467 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
468 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
472 private Optional<SubstitutionMapping> createSubstitutionMapping(final Component component,
473 final Map<String, Component> componentCache) throws ToscaExportException {
474 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
475 return Optional.empty();
478 final Either<String, ToscaError> toscaResourceNameEither = createComponentToscaName(component);
479 if (toscaResourceNameEither.isRight()) {
480 throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value());
482 final String toscaResourceName = toscaResourceNameEither.left().value();
484 final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
485 substitutionMapping.setNode_type(toscaResourceName);
486 convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter);
488 final Either<Map<String, String[]>, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache);
489 if (capabilitiesEither.isRight()) {
490 throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value());
492 final Map<String, String[]> capabilityMap = capabilitiesEither.left().value();
493 if (!capabilityMap.isEmpty()) {
494 substitutionMapping.setCapabilities(capabilityMap);
497 final Either<Map<String, String[]>, ToscaError> requirements =
498 capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache);
499 if (requirements.isRight()) {
500 throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value());
502 final Map<String, String[]> requirementMap = requirements.left().value();
503 if (MapUtils.isNotEmpty(requirementMap)) {
504 substitutionMapping.setRequirements(requirementMap);
507 final Map<String, String[]> propertyMappingMap = buildSubstitutionMappingPropertyMapping(component);
508 if (MapUtils.isNotEmpty(propertyMappingMap)) {
509 substitutionMapping.setProperties(propertyMappingMap);
512 final Map<String, String[]> attributesMappingMap = buildSubstitutionMappingAttributesMapping(component);
513 if (MapUtils.isNotEmpty(attributesMappingMap)) {
514 substitutionMapping.setAttributes(attributesMappingMap);
517 return Optional.of(substitutionMapping);
520 private Optional<NodeFilter> convertSubstitutionMappingFilter(final Component component) {
521 if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) {
522 return Optional.empty();
525 return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter()));
528 private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
529 Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
530 if (groups != null) {
531 topologyTemplate.addGroups(groups);
535 private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException {
536 Map<String, ToscaPolicyTemplate> policies = policyExportParser.getPolicies(component);
537 if (policies != null) {
538 topologyTemplate.addPolicies(policies);
542 private Map<String, String> convertMetadata(Component component) {
543 return convertMetadata(component, false, null);
546 private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) {
547 Map<String, String> toscaMetadata = new LinkedHashMap<>();
548 toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID());
549 toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID());
551 .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
552 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
553 List<CategoryDefinition> categories = component.getCategories();
554 CategoryDefinition categoryDefinition = categories.get(0);
555 toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
556 toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
558 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
559 toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID());
560 if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) {
561 toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion());
562 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant());
563 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid());
564 toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName());
565 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
566 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
567 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue());
568 } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
569 toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(),
570 componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue());
572 toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription());
575 switch (component.getComponentType()) {
577 Resource resource = (Resource) component;
578 if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
579 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) {
580 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue());
582 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name());
584 toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName());
585 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName());
586 toscaMetadata.put(JsonPresentationFields.TENANT.getPresentation(), resource.getTenant());
587 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease());
588 toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber());
591 Service service = (Service) component;
592 toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue());
593 toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType());
594 toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole());
595 toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction());
596 toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext());
597 toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),
598 service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType());
601 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
602 toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString());
603 toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy());
607 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
609 for (final String key : component.getCategorySpecificMetadata().keySet()) {
610 if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) {
611 toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key));
614 return toscaMetadata;
617 private String convertMetadataKey(JsonPresentationFields jsonPresentationField) {
618 if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) {
619 return INVARIANT_UUID;
621 return jsonPresentationField.getPresentation();
624 private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
625 final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
626 if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
627 log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
628 return Either.right(ToscaError.GENERAL_ERROR);
630 Map<String, Component> componentCache = new HashMap<>();
631 if (!ModelConverter.isAtomicComponent(component)) {
632 final List<Map<String, Map<String, String>>> additionalImports =
633 toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
634 List<Triple<String, String, Component>> dependencies = new ArrayList<>();
635 Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
636 final Map<String, Map<String, String>> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts);
637 if (!substituteTypeImportEntry.isEmpty()) {
638 additionalImports.add(substituteTypeImportEntry);
640 List<ComponentInstance> componentInstances = component.getComponentInstances();
641 if (componentInstances != null && !componentInstances.isEmpty()) {
642 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
644 toscaTemplate.setDependencies(dependencies);
645 toscaTemplate.setImports(additionalImports);
647 log.debug("currently imports supported for VF and service only");
649 return Either.left(new ImmutablePair<>(toscaTemplate, componentCache));
652 private Map<String, Map<String, String>> generateComponentSubstituteTypeImport(final Component component,
653 final Map<String, ArtifactDefinition> toscaArtifacts) {
655 if (component instanceof Service && !((Service) component).isSubstituteCandidate()) {
656 return Collections.emptyMap();
658 if (MapUtils.isEmpty(toscaArtifacts)) {
659 return Collections.emptyMap();
661 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
662 if (artifactDefinition == null) {
663 return Collections.emptyMap();
665 final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface";
666 return Map.of(importEntryName,
667 Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName()))
671 private List<Map<String, Map<String, String>>> getDefaultToscaImportConfig() {
672 return getConfiguration().getDefaultImports();
675 private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
676 final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
677 log.debug("createDependency componentCache {}", componentCache);
678 Component componentRI = componentCache.get(componentInstance.getComponentUid());
679 if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
680 // all resource must be only once!
681 final Either<Component, StorageOperationStatus> resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid());
682 if ((resource.isRight()) && (log.isDebugEnabled())) {
683 log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(),
684 componentInstance.getUniqueId());
687 final Component fetchedComponent = resource.left().value();
688 componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
689 addDependencies(imports, dependencies, componentRI);
694 * Sets a componentCache from the given component/resource.
696 private Component setComponentCache(final Map<String, Component> componentCache, final ComponentInstance componentInstance,
697 final Component fetchedComponent) {
698 componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent);
699 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy
700 || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
701 final Either<Component, StorageOperationStatus> sourceService = toscaOperationFacade
702 .getToscaFullElement(componentInstance.getSourceModelUid());
703 if (sourceService.isRight() && (log.isDebugEnabled())) {
704 log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(),
705 componentInstance.getUniqueId());
707 final Component fetchedSource = sourceService.left().value();
708 componentCache.put(fetchedSource.getUniqueId(), fetchedSource);
709 return fetchedSource;
711 return fetchedComponent;
715 * Retrieves all derived_from nodes and stores it in a predictable order.
717 private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
718 final Component fetchedComponent) {
719 final Set<Component> componentsList = new LinkedHashSet<>();
720 if (fetchedComponent instanceof Resource) {
721 log.debug("fetchedComponent is a resource {}", fetchedComponent);
722 final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
723 if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
724 derivedFromMapOfIdToName.get().entrySet().forEach(entry -> {
725 log.debug("Started entry.getValue() : {}", entry.getValue());
726 if (!NATIVE_ROOT.equals(entry.getValue())) {
727 Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey());
728 if (resourcefetched != null && resourcefetched.isLeft()) {
729 componentsList.add(resourcefetched.left().value());
733 setImports(imports, dependencies, componentsList);
735 setImports(imports, dependencies, fetchedComponent);
741 * Returns all derived_from nodes found.
743 private Optional<Map<String, String>> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set<Component> componentsList) {
744 final Resource parentResource = (Resource) fetchedComponent;
745 Map<String, String> derivedFromMapOfIdToName = new HashMap<>();
746 if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) {
747 componentsList.add(fetchedComponent);
748 for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) {
749 final Either<Resource, StorageOperationStatus> resourcefetched = toscaOperationFacade
750 .getToscaElement(componentInstance.getComponentUid());
751 if (resourcefetched != null && resourcefetched.isLeft()) {
752 final Map<String, String> derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName();
753 if (MapUtils.isNotEmpty(derivedWithId)) {
754 derivedFromMapOfIdToName.putAll(derivedWithId);
759 derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName();
761 log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName);
762 return Optional.ofNullable(derivedFromMapOfIdToName);
766 * Creates a resource map and adds it to the import list.
768 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
769 final Set<Component> componentsList) {
770 componentsList.forEach(component -> setImports(imports, dependencies, component));
773 private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
774 final Component component) {
775 final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
776 final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE);
777 if (artifactDefinition != null) {
778 final Map<String, String> files = new HashMap<>();
779 final String artifactName = artifactDefinition.getArtifactName();
780 files.put(IMPORTS_FILE_KEY, artifactName);
781 final StringBuilder keyNameBuilder = new StringBuilder();
782 keyNameBuilder.append(component.getComponentType().toString().toLowerCase());
783 keyNameBuilder.append("-");
784 keyNameBuilder.append(component.getName());
785 addImports(imports, keyNameBuilder, files);
786 dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component));
787 if (!ModelConverter.isAtomicComponent(component)) {
788 final Map<String, String> interfaceFiles = new HashMap<>();
789 interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName));
790 keyNameBuilder.append("-interface");
791 addImports(imports, keyNameBuilder, interfaceFiles);
797 * Adds the found resource to the import definition list.
799 private void addImports(final List<Map<String, Map<String, String>>> imports, final StringBuilder keyNameBuilder,
800 final Map<String, String> files) {
801 final String mapKey = keyNameBuilder.toString();
802 if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) {
803 final Map<String, Map<String, String>> importsListMember = new HashMap<>();
804 importsListMember.put(keyNameBuilder.toString(), files);
805 imports.add(importsListMember);
809 private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
810 Map<String, ToscaNodeType> nodeTypes) {
811 return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
814 public Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache, Component component,
815 ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes,
816 boolean isAssociatedComponent) {
817 log.debug("start convert node type for {}", component.getUniqueId());
818 ToscaNodeType toscaNodeType = createNodeType(component);
819 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation
820 .getAllInterfaceLifecycleTypes(component.getModel());
821 if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) {
822 log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value());
823 return Either.right(ToscaError.GENERAL_ERROR);
825 if (lifecycleTypeEither.isLeft()) {
826 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType)
827 .collect(Collectors.toList());
828 toscaNode.setInterface_types(interfacesOperationsConverter.addInterfaceTypeElement(component, allGlobalInterfaceTypes));
830 final var dataTypesEither = applicationDataTypeCache.getAll(component.getModel());
831 if (dataTypesEither.isRight()) {
832 log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
833 return Either.right(ToscaError.GENERAL_ERROR);
835 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
836 List<InputDefinition> inputDef = component.getInputs();
837 interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
838 final var toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
839 if (!toscaAttributeMap.isEmpty()) {
840 toscaNodeType.setAttributes(toscaAttributeMap);
842 final var mergedProperties = convertInputsToProperties(dataTypes, inputDef, component.getUniqueId());
843 if (CollectionUtils.isNotEmpty(component.getProperties())) {
844 List<PropertyDefinition> properties = component.getProperties();
845 Map<String, ToscaProperty> convertedProperties = properties.stream()
846 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors
847 .toMap(PropertyDataDefinition::getName,
848 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
849 // merge component properties and inputs properties
850 mergedProperties.putAll(convertedProperties);
852 if (MapUtils.isNotEmpty(mergedProperties)) {
853 toscaNodeType.setProperties(mergedProperties);
855 /* convert private data_types */
856 List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
857 if (CollectionUtils.isNotEmpty(privateDataTypes)) {
858 Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
859 for (DataTypeDefinition dataType : privateDataTypes) {
860 log.debug("Emitting private data type: component.name={} dataType.name={}",
861 component.getNormalizedName(), dataType.getName());
862 ToscaDataType toscaDataType = new ToscaDataType();
863 toscaDataType.setDerived_from(dataType.getDerivedFromName());
864 toscaDataType.setDescription(dataType.getDescription());
865 toscaDataType.setVersion(dataType.getVersion());
866 if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
867 toscaDataType.setProperties(dataType.getProperties().stream()
868 .collect(Collectors.toMap(
869 PropertyDataDefinition::getName,
870 s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY),
871 (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated,
875 toscaDataTypeMap.put(dataType.getName(), toscaDataType);
877 toscaNode.setData_types(toscaDataTypeMap);
880 // Extracted to method for code reuse
881 return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
884 private ToscaProperty validateToscaProperty(final List<DataTypeDefinition> privateDataTypes, final ToscaProperty toscaPropertyTobeValidated,
885 final ToscaProperty toscaProperty) {
886 final Optional<DataTypeDefinition> match = privateDataTypes.stream()
887 .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst();
888 return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty;
891 private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
892 final Map<String, DataTypeDefinition> dataTypes) {
893 if (CollectionUtils.isEmpty(attributeList)) {
894 return Collections.emptyMap();
896 final AttributeConverter converter = new AttributeConverter(dataTypes);
897 final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
898 for (final AttributeDefinition attributeDefinition : attributeList) {
899 toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition));
901 return toscaAttributeMap;
904 private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
905 Component component, ToscaTemplate toscaNode,
906 Map<String, ToscaNodeType> nodeTypes,
907 ToscaNodeType toscaNodeType,
908 Map<String, DataTypeDefinition> dataTypes) {
909 Either<ToscaNodeType, ToscaError> capabilities = convertCapabilities(componentsCache, component, toscaNodeType,
911 if (capabilities.isRight()) {
912 return Either.right(capabilities.right().value());
914 toscaNodeType = capabilities.left().value();
915 log.debug("Capabilities converted for {}", component.getUniqueId());
917 Either<ToscaNodeType, ToscaError> requirements = capabilityRequirementConverter
918 .convertRequirements(componentsCache, component, toscaNodeType);
919 if (requirements.isRight()) {
920 return Either.right(requirements.right().value());
922 toscaNodeType = requirements.left().value();
923 log.debug("Requirements converted for {}", component.getUniqueId());
925 String toscaResourceName;
926 switch (component.getComponentType()) {
928 toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition()
929 .getMetadataDataDefinition()).getToscaResourceName();
932 toscaResourceName = SERVICE_NODE_TYPE_PREFIX
933 + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName();
936 log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType());
937 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
940 nodeTypes.put(toscaResourceName, toscaNodeType);
941 toscaNode.setNode_types(nodeTypes);
942 log.debug("finish convert node type for {}", component.getUniqueId());
943 return Either.left(toscaNode);
946 private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(final Component component,
947 final Map<String, Component> componentCache,
948 final Map<String, DataTypeDefinition> dataTypes,
949 final ToscaTopolgyTemplate topologyTemplate) {
951 final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
952 final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes = component.getComponentInstancesAttributes();
953 final Map<String, List<ComponentInstanceInput>> componentInstancesInputs = component.getComponentInstancesInputs();
954 final Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = component.getComponentInstancesInterfaces();
955 final List<RequirementCapabilityRelDef> componentInstancesRelations = component.getComponentInstancesRelations();
957 Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplatesRes = null;
958 log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
959 final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
961 Map<String, ToscaGroupTemplate> groupsMap = null;
962 for (final ComponentInstance componentInstance : component.getComponentInstances()) {
963 ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
964 if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) {
965 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
967 if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences() != null) {
968 List<Object> occur = new ArrayList<>();
969 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
970 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
971 nodeTemplate.setOccurrences(occur);
973 if (componentInstance.getInstanceCount() != null) {
974 ObjectMapper objectMapper = new ObjectMapper();
975 Object obj = convertToToscaObject(componentInstance.getInstanceCount());
977 Map<String, String> map = objectMapper.convertValue(obj, Map.class);
978 nodeTemplate.setInstance_count(map);
981 nodeTemplate.setType(componentInstance.getToscaComponentName());
982 nodeTemplate.setDirectives(componentInstance.getDirectives());
983 NodeFilter nodeFilter = convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter());
984 if(nodeFilter != null && nodeFilter.hasData()){
985 nodeTemplate.setNode_filter(nodeFilter);
987 final Either<Component, Boolean> originComponentRes = capabilityRequirementConverter
988 .getOriginComponent(componentCache, componentInstance);
989 if (originComponentRes.isRight()) {
990 convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
993 final Either<ToscaNodeTemplate, ToscaError> requirements = convertComponentInstanceRequirements(component, componentInstance,
994 componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache);
995 if (requirements.isRight()) {
996 convertNodeTemplatesRes = Either.right(requirements.right().value());
999 final String instanceUniqueId = componentInstance.getUniqueId();
1000 log.debug("Component instance Requirements converted for instance {}", instanceUniqueId);
1002 nodeTemplate = requirements.left().value();
1004 final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid());
1006 if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
1007 final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid());
1008 nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance));
1010 nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance));
1013 final Either<ToscaNodeTemplate, ToscaError> capabilities =
1014 capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate);
1015 if (capabilities.isRight()) {
1016 convertNodeTemplatesRes = Either.right(capabilities.right().value());
1019 log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId);
1021 nodeTemplate = capabilities.left().value();
1022 final Map<String, Object> props = new HashMap<>();
1023 final Map<String, Object> attribs = new HashMap<>();
1025 if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) {
1026 // Adds the properties of parent component to map
1027 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
1028 addAttributesOfParentComponent(originalComponent, attribs);
1031 if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
1032 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props);
1034 if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1035 addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs);
1038 if (componentInstancesInputs != null
1039 && componentInstancesInputs.containsKey(instanceUniqueId)
1040 && !isComponentOfTypeServiceProxy(componentInstance)) {
1041 //For service proxy the inputs are already handled under instance properties above
1042 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props);
1045 //M3[00001] - NODE TEMPLATE INTERFACES - START
1046 handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component);
1047 //M3[00001] - NODE TEMPLATE INTERFACES - END
1048 if (MapUtils.isNotEmpty(props)) {
1049 nodeTemplate.setProperties(props);
1051 if (MapUtils.isNotEmpty(attribs)) {
1052 nodeTemplate.setAttributes(attribs);
1055 final List<GroupInstance> groupInstances = componentInstance.getGroupInstances();
1056 if (CollectionUtils.isNotEmpty(groupInstances)) {
1057 if (groupsMap == null) {
1058 groupsMap = new HashMap<>();
1060 for (final GroupInstance groupInst : groupInstances) {
1061 if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) {
1062 groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName()));
1067 nodeTemplates.put(componentInstance.getName(), nodeTemplate);
1069 if (groupsMap != null) {
1070 log.debug("instance groups added");
1071 topologyTemplate.addGroups(groupsMap);
1073 if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty(
1074 ((Service) component).getForwardingPaths())) {
1075 log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1076 ForwardingPathToscaUtil
1077 .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade);
1078 log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName());
1080 if (convertNodeTemplatesRes == null) {
1081 convertNodeTemplatesRes = Either.left(nodeTemplates);
1083 log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
1084 return convertNodeTemplatesRes;
1087 private Object convertToToscaObject(String value) {
1089 ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
1090 StringReader reader = new StringReader(value);
1091 JsonReader jsonReader = new JsonReader(reader);
1092 jsonReader.setLenient(true);
1093 JsonElement jsonElement = JsonParser.parseReader(jsonReader);
1094 if (jsonElement.isJsonObject()) {
1095 JsonObject jsonObj = jsonElement.getAsJsonObject();
1096 if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
1097 return mapConverterInst.handleComplexJsonValue(jsonElement);
1101 } catch (Exception e) {
1102 log.debug("convertToToscaValue failed to parse json value :", e);
1107 private Object parseToIntIfPossible(final String value) {
1108 final Integer intValue = Ints.tryParse(value);
1109 return intValue == null ? value : intValue;
1112 private void handleInstanceInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
1113 ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
1114 ToscaNodeTemplate nodeTemplate, String instanceUniqueId, Component parentComponent) {
1116 if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
1117 nodeTemplate.setInterfaces(null);
1121 final List<ComponentInstanceInterface> currServiceInterfaces = componentInstanceInterfaces.get(instanceUniqueId);
1123 final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
1124 currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface.getUniqueId(), instInterface));
1126 final Map<String, Object> interfaceMap = interfacesOperationsConverter
1127 .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance));
1129 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1130 nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1133 private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
1134 return Objects.nonNull(componentInstance.getOriginType())
1135 && componentInstance.getOriginType().getValue().equals("Service Proxy");
1138 private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
1139 Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
1140 String instanceUniqueId, Map<String, Object> props) {
1142 List<ComponentInstanceInput> instanceInputsList = componentInstancesInputs.get(instanceUniqueId);
1143 if (instanceInputsList != null) {
1144 instanceInputsList.forEach(input -> {
1145 Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue()
1146 : input.getDefaultValue();
1147 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
1152 private void addPropertiesOfComponentInstance(final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
1153 final Map<String, DataTypeDefinition> dataTypes,
1154 final String instanceUniqueId,
1155 final Map<String, Object> props) {
1157 if (isNotEmpty(componentInstancesProperties)) {
1158 componentInstancesProperties.get(instanceUniqueId)
1159 // Converts and adds each value to property map
1160 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue));
1164 private void addAttributesOfComponentInstance(final Map<String, List<ComponentInstanceAttribute>> componentInstancesAttributes,
1165 final String instanceUniqueId,
1166 final Map<String, Object> attribs) {
1168 if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) {
1169 componentInstancesAttributes.get(instanceUniqueId)
1170 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1174 private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
1175 Component componentOfInstance, Map<String, Object> props) {
1177 List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
1178 if (isNotEmpty(componentProperties)) {
1179 componentProperties.stream()
1180 // Filters out properties with empty default values
1181 .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
1182 // Converts and adds each value to property map
1183 .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue));
1187 private void addAttributesOfParentComponent(final Component componentOfInstance, final Map<String, Object> attribs) {
1189 final List<AttributeDefinition> componentAttributes = componentOfInstance.getAttributes();
1190 if (isNotEmpty(componentAttributes)) {
1191 componentAttributes.stream()
1192 // Filters out Attributes with empty default values
1193 .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue()))
1194 // Converts and adds each value to attribute map
1195 .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition));
1199 private ToscaNodeType createNodeType(Component component) {
1200 ToscaNodeType toscaNodeType = new ToscaNodeType();
1201 if (ModelConverter.isAtomicComponent(component)) {
1202 if (((Resource) component).getDerivedFrom() != null) {
1203 toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0));
1205 toscaNodeType.setDescription(component.getDescription());
1207 String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType()
1209 toscaNodeType.setDerived_from(derivedFrom);
1211 return toscaNodeType;
1214 private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
1216 Map<String, Object> proxyInterfaceTypes = new HashMap<>();
1217 Either<Map<String, Object>, ToscaError> res = Either.left(proxyInterfaceTypes);
1218 List<ComponentInstance> componentInstances = container.getComponentInstances();
1219 if (CollectionUtils.isEmpty(componentInstances)) {
1222 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1223 componentInstances.stream()
1224 .filter(this::isComponentOfTypeServiceProxy)
1225 .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst));
1226 if (MapUtils.isEmpty(serviceProxyInstanceList)) {
1229 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1230 Component serviceComponent;
1231 ComponentParametersView componentParametersView = new ComponentParametersView();
1232 componentParametersView.disableAll();
1233 componentParametersView.setIgnoreInterfaces(false);
1234 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1235 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1236 if (service.isRight()) {
1237 log.debug("Failed to fetch original service component with id {} for instance {}",
1238 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1239 return Either.right(ToscaError.GENERAL_ERROR);
1241 serviceComponent = service.left().value();
1244 Either<Map<String, InterfaceDefinition>, StorageOperationStatus> lifecycleTypeEither =
1245 interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel());
1246 if (lifecycleTypeEither.isRight()) {
1247 log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value());
1248 return Either.right(ToscaError.GENERAL_ERROR);
1251 List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream()
1252 .map(InterfaceDataDefinition::getType)
1253 .collect(Collectors.toList());
1254 //Add interface types for local interfaces in the original service component for proxy
1255 Map<String, Object> localInterfaceTypes = interfacesOperationsConverter.addInterfaceTypeElement(serviceComponent,
1256 allGlobalInterfaceTypes);
1257 if (MapUtils.isNotEmpty(localInterfaceTypes)) {
1258 proxyInterfaceTypes.putAll(localInterfaceTypes);
1262 return Either.left(proxyInterfaceTypes);
1265 private Either<Map<String, ToscaNodeType>, ToscaError> createProxyNodeTypes(Map<String, Component> componentCache,
1266 Component container) {
1268 Map<String, ToscaNodeType> nodeTypesMap = new HashMap<>();
1269 Either<Map<String, ToscaNodeType>, ToscaError> res = Either.left(nodeTypesMap);
1271 List<ComponentInstance> componentInstances = container.getComponentInstances();
1273 if (componentInstances == null || componentInstances.isEmpty()) {
1276 Map<String, ComponentInstance> serviceProxyInstanceList = new HashMap<>();
1277 List<ComponentInstance> proxyInst = componentInstances.stream()
1278 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name()))
1279 .collect(Collectors.toList());
1280 if (proxyInst != null && !proxyInst.isEmpty()) {
1281 for (ComponentInstance inst : proxyInst) {
1282 serviceProxyInstanceList.put(inst.getToscaComponentName(), inst);
1286 if (serviceProxyInstanceList.isEmpty()) {
1289 Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade
1290 .getLatestByName("serviceProxy", null);
1291 if (serviceProxyOrigin.isRight()) {
1292 log.debug("Failed to fetch normative service proxy resource by tosca name, error {}",
1293 serviceProxyOrigin.right().value());
1294 return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE);
1296 Component origComponent = serviceProxyOrigin.left().value();
1298 for (Entry<String, ComponentInstance> entryProxy : serviceProxyInstanceList.entrySet()) {
1299 Component serviceComponent = null;
1300 ComponentParametersView componentParametersView = new ComponentParametersView();
1301 componentParametersView.disableAll();
1302 componentParametersView.setIgnoreCategories(false);
1303 componentParametersView.setIgnoreProperties(false);
1304 componentParametersView.setIgnoreInputs(false);
1305 componentParametersView.setIgnoreInterfaces(false);
1306 componentParametersView.setIgnoreRequirements(false);
1307 Either<Component, StorageOperationStatus> service = toscaOperationFacade
1308 .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView);
1309 if (service.isRight()) {
1310 log.debug("Failed to fetch resource with id {} for instance {}",
1311 entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName());
1313 serviceComponent = service.left().value();
1316 ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent,
1317 entryProxy.getValue());
1318 nodeTypesMap.put(entryProxy.getKey(), toscaNodeType);
1321 return Either.left(nodeTypesMap);
1324 private void createServiceSubstitutionNodeTypes(final Map<String, Component> componentCache,
1325 final Component container, final ToscaTemplate toscaNode) {
1326 final List<ComponentInstance> componentInstances = container.getComponentInstances();
1328 if (CollectionUtils.isEmpty(componentInstances)) {
1331 final List<ComponentInstance> serviceSubstitutionInstanceList = componentInstances.stream()
1332 .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name()))
1333 .collect(Collectors.toList());
1334 if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) {
1335 for (ComponentInstance inst : serviceSubstitutionInstanceList) {
1336 final Map<String, ToscaNodeType> nodeTypes =
1337 toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
1338 convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode,
1344 private ToscaNodeType createProxyNodeType(Map<String, Component> componentCache, Component origComponent,
1345 Component proxyComponent, ComponentInstance componentInstance) {
1346 ToscaNodeType toscaNodeType = new ToscaNodeType();
1347 String derivedFrom = ((Resource) origComponent).getToscaResourceName();
1349 toscaNodeType.setDerived_from(derivedFrom);
1350 Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(
1351 origComponent.getModel());
1352 if (dataTypesEither.isRight()) {
1353 log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value());
1355 Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
1356 Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter
1357 .convertProxyCapabilities(componentCache, componentInstance, dataTypes);
1359 if (MapUtils.isNotEmpty(capabilities)) {
1360 toscaNodeType.setCapabilities(capabilities);
1362 List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter
1363 .convertProxyRequirements(componentCache, componentInstance);
1364 if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) {
1365 toscaNodeType.setRequirements(proxyNodeTypeRequirements);
1367 Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes);
1368 proxyProperties.ifPresent(toscaNodeType::setProperties);
1370 Map<String, Object> interfaceMap = new HashMap<>();
1371 if (MapUtils.isEmpty(componentInstance.getInterfaces())) {
1372 final Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes);
1373 if (proxyInterfaces.isPresent()) {
1374 interfaceMap = proxyInterfaces.get();
1377 interfaceMap = interfacesOperationsConverter.getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false);
1380 interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap);
1381 toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap);
1383 return toscaNodeType;
1386 private Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceRequirements(Component component,
1387 ComponentInstance componentInstance,
1388 List<RequirementCapabilityRelDef> relations,
1389 ToscaNodeTemplate nodeTypeTemplate,
1390 Component originComponent,
1391 Map<String, Component> componentCache) {
1393 final List<RequirementCapabilityRelDef> requirementDefinitionList = filterRequirements(componentInstance,
1395 if (isNotEmpty(requirementDefinitionList)) {
1397 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = buildRequirements(component, componentInstance,
1398 requirementDefinitionList, originComponent, componentCache);
1399 if (!toscaRequirements.isEmpty()) {
1400 nodeTypeTemplate.setRequirements(toscaRequirements);
1402 } catch (final Exception e) {
1403 log.debug("Failed to convert component instance requirements for the component instance {}. ",
1404 componentInstance.getName(), e);
1405 return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
1408 log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName());
1409 return Either.left(nodeTypeTemplate);
1412 private List<Map<String, ToscaTemplateRequirement>> buildRequirements(final Component component,
1413 final ComponentInstance componentInstance,
1414 final List<RequirementCapabilityRelDef> filteredRelations,
1415 final Component originComponent,
1416 final Map<String, Component> componentCache)
1417 throws ToscaExportException {
1419 final List<Map<String, ToscaTemplateRequirement>> toscaRequirements = new ArrayList<>();
1420 for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) {
1421 final Map<String, ToscaTemplateRequirement> toscaTemplateRequirementMap =
1422 buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache);
1423 toscaRequirements.add(toscaTemplateRequirementMap);
1426 return toscaRequirements;
1429 private List<RequirementCapabilityRelDef> filterRequirements(ComponentInstance componentInstance,
1430 List<RequirementCapabilityRelDef> relations) {
1431 return relations.stream()
1432 .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList());
1435 private Map<String, ToscaTemplateRequirement> buildRequirement(final ComponentInstance fromInstance,
1436 final Component fromOriginComponent,
1437 final List<ComponentInstance> instancesList,
1438 final RequirementCapabilityRelDef relationshipDefinition,
1439 final Map<String, Component> componentCache)
1440 throws ToscaExportException {
1442 final Map<String, List<RequirementDefinition>> reqMap = fromOriginComponent.getRequirements();
1443 final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition
1444 .getRelationships().get(0);
1445 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1447 final ComponentInstance toInstance = instancesList.stream()
1448 .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId()))
1449 .findFirst().orElse(null);
1450 if (toInstance == null) {
1451 final String errorMsg = String
1452 .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(),
1453 relationshipDefinition.getToNode());
1454 log.debug(errorMsg);
1455 throw new ToscaExportException(errorMsg);
1457 final Optional<RequirementDefinition> reqOpt =
1458 findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId());
1459 if (reqOpt.isEmpty()) {
1460 final String errorMsg = String
1461 .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s",
1462 relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId());
1463 log.debug(errorMsg);
1464 throw new ToscaExportException(errorMsg);
1466 final ComponentParametersView filter = new ComponentParametersView(true);
1467 filter.setIgnoreComponentInstances(false);
1468 filter.setIgnoreCapabilities(false);
1469 filter.setIgnoreGroups(false);
1470 final Either<Component, StorageOperationStatus> getOriginRes =
1471 toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter);
1472 if (getOriginRes.isRight()) {
1473 final String errorMsg = String.format(
1474 "Failed to build substituted name for the requirement %s. "
1475 + "Failed to get an origin component with uniqueId %s",
1476 reqOpt.get().getName(), toInstance.getActualComponentUid());
1477 log.debug(errorMsg);
1478 throw new ToscaExportException(errorMsg);
1480 final Component toOriginComponent = getOriginRes.left().value();
1481 Optional<CapabilityDefinition> capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream()
1482 .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst();
1483 if (capOpt.isEmpty()) {
1484 capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get());
1485 if (capOpt.isEmpty()) {
1486 final String errorMsg = String
1487 .format("Failed to find a capability with name %s on a component with uniqueId %s",
1488 relationshipInfo.getCapability(), fromOriginComponent.getUniqueId());
1489 log.debug(errorMsg);
1490 throw new ToscaExportException(errorMsg);
1493 return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(),
1494 capabilityRequirementRelationship, toInstance, componentCache);
1497 private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair,
1498 CapabilityDefinition capability) {
1499 return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null
1500 && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId()));
1503 private Optional<CapabilityDefinition> findCapability(RelationshipInfo reqAndRelationshipPair,
1504 Component toOriginComponent, Component fromOriginComponent,
1505 RequirementDefinition requirement) {
1506 Optional<CapabilityDefinition> cap = toOriginComponent.getCapabilities().get(requirement.getCapability())
1507 .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst();
1508 if (!cap.isPresent()) {
1509 log.debug("Failed to find a capability with name {} on a component with uniqueId {}",
1510 reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId());
1515 private Map<String, ToscaTemplateRequirement> buildRequirement(final Component fromOriginComponent,
1516 final Component toOriginComponent,
1517 final CapabilityDefinition capability,
1518 final RequirementDefinition requirement,
1519 final CapabilityRequirementRelationship capabilityRequirementRelationship,
1520 final ComponentInstance toInstance,
1521 final Map<String, Component> componentCache)
1522 throws ToscaExportException {
1524 List<String> reducedPath = capability.getPath();
1525 if (capability.getOwnerId() != null) {
1526 reducedPath = capabilityRequirementConverter
1527 .getReducedPathByOwner(capability.getPath(), capability.getOwnerId());
1529 final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation();
1530 final Either<String, Boolean> capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache,
1531 toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName());
1532 if (capabilityNameEither.isRight()) {
1533 final String errorMsg = String.format(
1534 "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s",
1535 capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId());
1538 throw new ToscaExportException(errorMsg);
1540 final Either<String, Boolean> requirementNameEither = capabilityRequirementConverter
1541 .buildSubstitutedName(componentCache, fromOriginComponent,
1542 requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName());
1543 if (requirementNameEither.isRight()) {
1544 final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement "
1545 + "with name %s on a component with uniqueId %s",
1546 capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId());
1547 log.debug(errorMsg);
1548 throw new ToscaExportException(errorMsg);
1550 final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement();
1551 final Map<String, ToscaTemplateRequirement> toscaReqMap = new HashMap<>();
1552 toscaRequirement.setNode(toInstance.getName());
1553 toscaRequirement.setCapability(capabilityNameEither.left().value());
1554 if (isNotEmpty(capabilityRequirementRelationship.getOperations())) {
1555 toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship));
1557 toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement);
1561 private Optional<RequirementDefinition> findRequirement(Component fromOriginComponent,
1562 Map<String, List<RequirementDefinition>> reqMap,
1563 RelationshipInfo reqAndRelationshipPair,
1564 String fromInstanceId) {
1565 for (List<RequirementDefinition> reqList : reqMap.values()) {
1566 Optional<RequirementDefinition> reqOpt = reqList.stream().filter(
1567 r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId))
1569 if (reqOpt.isPresent()) {
1573 return Optional.empty();
1577 * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF
1578 * 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
1579 * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation
1581 private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair,
1582 RequirementDefinition requirement, String fromInstanceId) {
1583 if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) {
1584 log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(),
1585 reqAndRelationshipPair.getRequirement());
1588 return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId,
1592 private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId,
1593 Component originComponent) {
1594 return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (
1595 isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils
1596 .equals(requirement.getOwnerId(), originComponent.getUniqueId()));
1599 private boolean isCvfc(Component component) {
1600 return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC;
1603 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(final Component component,
1604 final Map<String, Component> componentCache) {
1605 Either<Map<String, String[]>, ToscaError> toscaCapabilitiesRes =
1606 capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component);
1607 if (toscaCapabilitiesRes.isRight()) {
1608 log.debug("Failed convert capabilities for the component {}. ", component.getName());
1609 return Either.right(toscaCapabilitiesRes.right().value());
1611 if (isNotEmpty(toscaCapabilitiesRes.left().value())) {
1612 log.debug("Finish convert capabilities for the component {}. ", component.getName());
1613 return Either.left(toscaCapabilitiesRes.left().value());
1615 log.debug("Finished to convert capabilities for the component {}. ", component.getName());
1617 return Either.left(Collections.emptyMap());
1620 private Either<ToscaNodeType, ToscaError> convertCapabilities(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType,
1621 Map<String, DataTypeDefinition> dataTypes) {
1622 Map<String, ToscaCapability> toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes);
1623 if (!toscaCapabilities.isEmpty()) {
1624 nodeType.setCapabilities(toscaCapabilities);
1626 log.debug("Finish convert Capabilities for node type");
1627 return Either.left(nodeType);
1630 private Map<String, ToscaTemplateArtifact> convertToNodeTemplateArtifacts(Map<String, ToscaArtifactDataDefinition> artifacts) {
1631 if (artifacts == null) {
1634 Map<String, ToscaTemplateArtifact> arts = new HashMap<>();
1635 for (Map.Entry<String, ToscaArtifactDataDefinition> entry : artifacts.entrySet()) {
1636 ToscaTemplateArtifact artifact = new ToscaTemplateArtifact();
1637 artifact.setFile(entry.getValue().getFile());
1638 artifact.setType(entry.getValue().getType());
1639 artifact.setProperties(entry.getValue().getProperties());
1640 arts.put(entry.getKey(), artifact);
1645 private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) {
1646 if (inNodeFilter == null) {
1649 NodeFilter nodeFilter = new NodeFilter();
1650 ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities();
1651 ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties();
1652 List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>();
1653 copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy);
1654 if (CollectionUtils.isNotEmpty(capabilitiesCopy)) {
1655 nodeFilter.setCapabilities(capabilitiesCopy);
1657 final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties);
1658 if (CollectionUtils.isNotEmpty(propertiesCopy)) {
1659 nodeFilter.setProperties(propertiesCopy);
1661 nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
1662 nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1666 private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
1667 if (substitutionFilterDataDefinition == null) {
1670 NodeFilter nodeFilter = new NodeFilter();
1671 final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties());
1672 if (!propertiesCopy.isEmpty()) {
1673 nodeFilter.setProperties(propertiesCopy);
1675 nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
1676 return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
1679 private Object cloneToscaId(Object toscaId) {
1680 return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
1683 private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
1684 String objectAsYml = yamlUtil.objectToYaml(objToClone);
1685 return yamlUtil.yamlToObject(objectAsYml, classOfObj);
1688 private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities,
1689 List<Map<String, CapabilityFilter>> capabilitiesCopy) {
1690 if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition()
1694 for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) {
1695 Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>();
1696 final var capabilityFilter = new CapabilityFilter();
1697 capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties()));
1698 capabilityFilterCopyMap.put(capability.getName(), capabilityFilter);
1699 capabilitiesCopy.add(capabilityFilterCopyMap);
1703 private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) {
1704 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1705 return Collections.emptyList();
1707 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1708 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1709 for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1710 final String propertyName = propertyFilter.getName();
1711 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1712 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1713 if (constraints == null) {
1714 constraints = new ArrayList<>();
1716 constraints.add(buildNodeFilterValue(filterConstraint));
1721 propertyFilterDefinitionMap.entrySet().stream()
1722 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1723 .forEach(propertiesCopy::add);
1724 return propertiesCopy;
1727 private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter(
1728 final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) {
1730 if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) {
1731 return Collections.emptyList();
1733 List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>();
1734 Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>();
1735 for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) {
1736 final String propertyName = propertyFilter.getName();
1737 for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) {
1738 propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> {
1739 if (constraints == null) {
1740 constraints = new ArrayList<>();
1742 constraints.add(buildNodeFilterValue(filterConstraint));
1747 propertyFilterDefinitionMap.entrySet().stream()
1748 .map(entry -> Map.of(entry.getKey(), entry.getValue()))
1749 .forEach(propertiesCopy::add);
1750 return propertiesCopy;
1753 private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) {
1754 if (filterConstraint.getValue() instanceof ToscaFunction) {
1755 return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue());
1757 return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue());
1761 private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) {
1762 if (component == null || CollectionUtils.isEmpty(component.getInputs())) {
1763 return Collections.emptyMap();
1765 return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName)
1766 .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1));
1769 private Map<String, String[]> buildSubstitutionMappingAttributesMapping(final Component component) {
1770 if (component == null || CollectionUtils.isEmpty(component.getOutputs())) {
1771 return Collections.emptyMap();
1773 return component.getOutputs().stream().map(AttributeDataDefinition::getName)
1774 .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1));
1777 private Optional<Map<String, ToscaProperty>> getProxyNodeTypeProperties(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1778 if (Objects.isNull(proxyComponent)) {
1779 return Optional.empty();
1781 final var proxyProperties = convertInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyComponent.getUniqueId());
1782 if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) {
1783 proxyProperties.putAll(proxyComponent.getProperties().stream()
1784 .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors
1785 .toMap(PropertyDataDefinition::getName,
1786 property -> propertyConvertor.convertProperty(dataTypes, property, PropertyType.PROPERTY))));
1788 return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty();
1791 private Map<String, ToscaProperty> convertInputsToProperties(Map<String, DataTypeDefinition> dataTypes, List<InputDefinition> componentInputs,
1792 String componentUniqueId) {
1793 if (CollectionUtils.isEmpty(componentInputs)) {
1794 return new HashMap<>();
1796 return componentInputs.stream().filter(input -> componentUniqueId.equals(input.getInstanceUniqueId()))
1797 .collect(Collectors.toMap(InputDefinition::getName, i -> propertyConvertor.convertProperty(dataTypes, i, PropertyType.INPUT)));
1800 private Optional<Map<String, Object>> getProxyNodeTypeInterfaces(Component proxyComponent, Map<String, DataTypeDefinition> dataTypes) {
1801 if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) {
1802 return Optional.empty();
1804 Map<String, InterfaceDefinition> proxyComponentInterfaces = proxyComponent.getInterfaces();
1805 //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is
1807 // always available in the proxy node template
1808 removeOperationImplementationForProxyNodeType(proxyComponentInterfaces);
1809 return Optional.ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false));
1812 private static class CustomRepresenter extends Representer {
1814 CustomRepresenter() {
1816 this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
1817 this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
1818 // null representer is exceptional and it is stored as an instance
1821 this.nullRepresenter = new RepresentNull();
1824 public boolean validateGetInputValue(final Object valueObj) {
1825 if (!(valueObj instanceof List) && !(valueObj instanceof String)) {
1828 if (valueObj instanceof List) {
1829 return ((List) valueObj).size() > 1;
1834 public boolean validateGetPropertyOrAttributeValue(final Object valueObj) {
1835 if (valueObj instanceof List) {
1836 return ((List) valueObj).size() > 1;
1842 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
1843 if (propertyValue == null) {
1846 // skip not relevant for Tosca property
1847 if ("dependencies".equals(property.getName())) {
1850 if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) {
1853 if (javaBean instanceof ToscaPropertyConstraint) {
1854 return handleToscaPropertyConstraint((ToscaPropertyConstraint)javaBean, property, propertyValue, customTag);
1856 removeDefaultP(propertyValue);
1857 NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1858 if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) {
1859 return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode());
1861 return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode;
1864 private NodeTuple handleToscaPropertyConstraint(final ToscaPropertyConstraint javaBean, final Property property, final Object propertyValue,
1865 final Tag customTag) {
1866 final NodeTuple nodeTuple = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
1867 final String entryToscaName = javaBean.getEntryToscaName(property.getName());
1868 return new NodeTuple(representData(entryToscaName), nodeTuple.getValueNode());
1871 private void removeDefaultP(final Object propertyValue) {
1872 if (propertyValue instanceof Map) {
1873 final Map mapPropertyValue = ((Map) propertyValue);
1874 final Iterator<Entry> iter = mapPropertyValue.entrySet().iterator();
1875 Object defaultValue = null;
1876 while (iter.hasNext()) {
1877 final Map.Entry entry = iter.next();
1878 if ("_defaultp_".equals(entry.getKey())) {
1879 defaultValue = entry.getValue();
1881 } else if (entry.getValue() instanceof Map) {
1882 removeDefaultP(entry.getValue());
1885 if (defaultValue != null) {
1886 mapPropertyValue.putIfAbsent("default", defaultValue);
1892 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
1893 // remove the bean type from the output yaml (!! ...)
1894 if (!classTags.containsKey(javaBean.getClass())) {
1895 addClassTag(javaBean.getClass(), Tag.MAP);
1897 return super.representJavaBean(properties, javaBean);
1900 private class RepresentToscaAttribute implements Represent {
1903 public Node representData(Object data) {
1904 final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
1905 return represent(toscaAttribute.asToscaMap());
1909 private class RepresentToscaPropertyAssignment implements Represent {
1911 public Node representData(Object data) {
1912 final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data;
1913 if (toscaOperationAssignment.getValue() instanceof String) {
1914 final String stringValue = (String) toscaOperationAssignment.getValue();
1915 if (isPropertyOrAttributeFunction(stringValue)) {
1916 return representGetAttribute(stringValue);
1918 return representScalar(Tag.STR, stringValue);
1920 return represent(null);
1923 public Node representGetAttribute(final String getAttributeFunction) {
1924 return represent(new Yaml().load(getAttributeFunction));
1927 public boolean isPropertyOrAttributeFunction(final String value) {
1929 final Yaml yaml = new Yaml();
1930 final Object yamlObj = yaml.load(value);
1931 if (!(yamlObj instanceof Map)) {
1934 final Map<String, Object> getAttributeMap = (Map) yamlObj;
1935 if (getAttributeMap.size() != 1) {
1938 final List<String> functionList = Arrays
1939 .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName());
1940 final Optional<String> function = getAttributeMap.keySet().stream()
1941 .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst();
1942 if (function.isEmpty()) {
1945 final String functionName = function.get();
1946 final Object getAttributeValueObj = getAttributeMap.get(functionName);
1947 if (GET_INPUT.getFunctionName().equals(functionName)) {
1948 return validateGetInputValue(getAttributeValueObj);
1950 return validateGetPropertyOrAttributeValue(getAttributeValueObj);
1952 } catch (final Exception ignored) {
1958 private class RepresentNull implements Represent {
1961 public Node representData(Object data) {
1962 // possible values are here http://yaml.org/type/null.html
1963 return representScalar(Tag.NULL, "");
1968 private static class UnsortedPropertyUtils extends PropertyUtils {
1971 protected Set<Property> createPropertySet(Class type, BeanAccess bAccess) {
1972 Collection<Property> fields = getPropertiesMap(type, BeanAccess.FIELD).values();
1973 return new LinkedHashSet<>(fields);
1977 private Configuration getConfiguration() {
1978 return ConfigurationManager.getConfigurationManager().getConfiguration();