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=========================================================
21 package org.openecomp.sdc.be.tosca;
23 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
24 import static org.apache.commons.lang3.StringUtils.isBlank;
25 import static org.apache.commons.lang3.StringUtils.isNoneBlank;
27 import com.google.common.collect.Iterables;
28 import com.google.common.collect.Maps;
29 import fj.data.Either;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
36 import java.util.Optional;
37 import java.util.function.Function;
38 import java.util.stream.Collectors;
39 import org.apache.commons.collections.CollectionUtils;
40 import org.apache.commons.collections.MapUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.apache.commons.lang3.tuple.ImmutablePair;
43 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
45 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
46 import org.openecomp.sdc.be.model.CapabilityDefinition;
47 import org.openecomp.sdc.be.model.Component;
48 import org.openecomp.sdc.be.model.ComponentInstance;
49 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
50 import org.openecomp.sdc.be.model.ComponentParametersView;
51 import org.openecomp.sdc.be.model.DataTypeDefinition;
52 import org.openecomp.sdc.be.model.GroupDefinition;
53 import org.openecomp.sdc.be.model.PropertyDefinition;
54 import org.openecomp.sdc.be.model.RequirementDefinition;
55 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
56 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
57 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
58 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
59 import org.openecomp.sdc.be.tosca.ToscaUtils.SubstitutionEntry;
60 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
61 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
62 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
63 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
64 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
65 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
66 import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
67 import org.openecomp.sdc.common.log.wrappers.Logger;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.context.annotation.Scope;
72 * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
75 @org.springframework.stereotype.Component("capabilty-requirement-convertor")
76 @Scope(value = "singleton")
77 public class CapabilityRequirementConverter {
79 private static final String NO_CAPABILITIES = "No Capabilities for node type";
80 private static final String NO_REQUIREMENTS = "No Requirements for node type";
81 private static CapabilityRequirementConverter instance;
82 private static final Logger logger = Logger.getLogger(CapabilityRequirementConverter.class);
83 private static final String PATH_DELIMITER = ".";
84 private static final String FAILED_TO_FIND_CI_IN_PATH ="Failed to find ci in the path is {} component {}";
87 private ToscaOperationFacade toscaOperationFacade;
89 private PropertyConvertor propertyConvertor;
91 public CapabilityRequirementConverter() {}
93 public static synchronized CapabilityRequirementConverter getInstance() {
94 if (instance == null) {
95 instance = new CapabilityRequirementConverter();
100 public String buildCapabilityNameForComponentInstance( Map<String,Component> componentCache , ComponentInstance componentInstance, CapabilityDefinition c) {
101 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
102 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())){
103 return buildSubstitutedName(componentCache, c.getName(), c.getPreviousName(), c.getPath(), c.getOwnerId(), componentInstance)
105 .orValue(c.getName());
107 return c.getPreviousName();
110 public String buildRequirementNameForComponentInstance(Map<String,Component> componentCache,
111 ComponentInstance componentInstance,
112 RequirementDefinition r) {
113 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
114 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
115 return buildSubstitutedName(componentCache, r.getName(), r.getPreviousName(), r.getPath(), r.getOwnerId(),
116 componentInstance).left()
117 .orValue(r.getName());
119 return r.getPreviousName();
122 private String buildCapReqNamePrefix(String normalizedName) {
123 return normalizedName + PATH_DELIMITER;
127 * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
128 * @param componentInstance
130 * @param nodeTemplate
133 public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilities(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
135 Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
136 Map<String,Component> componentCache = new HashMap<>();
137 if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
138 Map<String, ToscaTemplateCapability> capabilities = new HashMap<>();
139 capabilitiesInst.entrySet().forEach( e -> {
140 List<CapabilityDefinition> capList = e.getValue();
141 if ( capList != null && !capList.isEmpty() ) {
143 .forEach( c -> convertOverridenProperties( componentInstance, dataTypes, capabilities, c ,
144 buildCapabilityNameForComponentInstance( componentCache , componentInstance , c )));
147 if (MapUtils.isNotEmpty(capabilities)) {
148 nodeTemplate.setCapabilities(capabilities);
151 return Either.left(nodeTemplate);
154 private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c , String capabilityName) {
155 if (isNotEmpty(c.getProperties())) {
158 .filter(p -> p.getValue() != null || p.getDefaultValue() != null)
159 .forEach(p -> convertOverriddenProperty(componentInstance, dataTypes, capabilties , p ,capabilityName));
163 private void convertOverriddenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, ComponentInstanceProperty p , String capabilityName) {
164 if (logger.isDebugEnabled()) {
165 logger.debug("Exist d property {} for capability {} with value {}", p.getName(), capabilityName, p.getValue());
167 ToscaTemplateCapability toscaTemplateCapability = capabilties.computeIfAbsent( capabilityName , key -> new ToscaTemplateCapability() );
169 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
170 if (toscaCapProp == null) {
171 toscaCapProp = new HashMap<>();
173 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
174 toscaCapProp.put(p.getName(), convertedValue);
175 toscaTemplateCapability.setProperties(toscaCapProp);
178 private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
179 logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
180 String propertyType = prop.getType();
181 String innerType = null;
182 if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
183 innerType = prop.getSchema().getProperty().getType();
185 String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
186 return propertyConvertor.convertToToscaObject(prop, propValue, dataTypes, false);
189 * Allows to convert requirements of a node type to tosca template requirements representation
194 public Either<ToscaNodeType, ToscaError> convertRequirements(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType) {
195 List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(componentsCache, component);
196 if (!toscaRequirements.isEmpty()) {
197 nodeType.setRequirements(toscaRequirements);
199 logger.debug("Finish convert Requirements for node type");
201 return Either.left(nodeType);
205 * Allows to convert component requirements to the tosca template substitution mappings requirements
206 * @param componentsCache
208 * @param substitutionMappings
211 public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String,Component> componentsCache, Component component, SubstitutionMapping substitutionMappings) {
212 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
213 Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
214 if(toscaRequirementsRes.isRight()){
215 result = Either.right(toscaRequirementsRes.right().value());
216 logger.debug("Failed convert requirements for the component {}. ", component.getName());
217 } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
218 substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
219 result = Either.left(substitutionMappings);
220 logger.debug("Finish convert requirements for the component {}. ", component.getName());
226 * Allows to convert requirements of a server proxy node type to tosca template requirements
227 * @param instanceProxy
228 * @return converted tosca template requirements
230 List<Map<String, ToscaRequirement>> convertProxyRequirements(Map<String, Component> componentCache,
231 ComponentInstance instanceProxy) {
232 Map<String, List<RequirementDefinition>> requirements = instanceProxy.getRequirements();
233 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
234 if (requirements != null) {
235 requirements.entrySet().stream()
236 .flatMap(e -> e.getValue().stream())
238 ImmutablePair<String, ToscaRequirement> pair = convertProxyRequirement(
239 buildRequirementNameForComponentInstance(componentCache, instanceProxy, req), req);
240 Map<String, ToscaRequirement> requirement = new HashMap<>();
241 requirement.put(pair.left, pair.right);
242 toscaRequirements.add(requirement);
245 logger.debug(NO_REQUIREMENTS);
248 return toscaRequirements;
251 private ImmutablePair<String, ToscaRequirement> convertProxyRequirement(String requirementName,
252 RequirementDefinition r) {
253 ToscaRequirement toscaRequirement = createToscaRequirement(r);
254 return new ImmutablePair<>(requirementName, toscaRequirement);
257 private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Map<String, Component> componentsCache, Component component) {
258 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
259 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
260 if (requirements != null) {
261 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
262 entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
263 ImmutablePair<String, ToscaRequirement> pair = convertRequirement(componentsCache, component, ModelConverter.isAtomicComponent(component), r);
264 Map<String, ToscaRequirement> requirement = new HashMap<>();
266 requirement.put(pair.left, pair.right);
267 toscaRequirements.add(requirement);
269 logger.debug("Finish convert Requirements for node type");
272 logger.debug(NO_REQUIREMENTS);
274 return toscaRequirements;
277 private boolean filter(Component component, String ownerId) {
278 return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null);
281 private boolean isNodeTypeOwner(Component component, String ownerId) {
282 return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
285 private String dropLast( String path, String delimiter ) {
286 if (isBlank(path) || isBlank(delimiter)){
289 return path.substring(0, path.lastIndexOf(delimiter));
292 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
293 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
294 Either<Map<String, String[]>, ToscaError> result;
295 if (requirements != null) {
296 result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
298 result = Either.left(Maps.newHashMap());
299 logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
304 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache, Component component, Map<String, List<RequirementDefinition>> requirements) {
306 Map<String, String[]> toscaRequirements = new HashMap<>();
307 Either<Map<String, String[]>, ToscaError> result = null;
308 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
309 Optional<RequirementDefinition> failedToAddRequirement = entry.getValue()
311 .filter(r->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), r.getPreviousName(), r.getOwnerId(), r.getPath()))
313 if(failedToAddRequirement.isPresent()){
314 logger.debug("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
315 failedToAddRequirement.get().getName(), component.getName());
316 result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
318 logger.debug("Finish convert requirements for the component {}. ", component.getName());
321 result = Either.left(toscaRequirements);
326 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
328 Map<String, String[]> toscaCapabilities = new HashMap<>();
329 Either<Map<String, String[]>, ToscaError> result = null;
330 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
331 Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
333 .filter(c->!addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath()))
335 if(failedToAddRequirement.isPresent()){
336 logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ",
337 failedToAddRequirement.get().getName(), component.getName());
338 result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
340 logger.debug("Finish convert capabilities for the component {}. ", component.getName());
343 result = Either.left(toscaCapabilities);
348 private boolean addEntry(Map<String, Component> componentsCache, Map<String, String[]> capReqMap, Component component, SubstitutionEntry entry, String previousName, String ownerId, List<String> path){
350 if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, entry.getFullName(), previousName, path, ownerId, entry)){
353 logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
354 if (StringUtils.isNotEmpty(entry.getSourceName())) {
355 addEntry(capReqMap, component, path, entry);
357 logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
362 private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
363 return ToscaUtils.isNotComplexVfc(component) && isNotEmpty(path) && path.iterator().hasNext();
366 private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path, String ownerId, SubstitutionEntry entry) {
370 if(CollectionUtils.isNotEmpty(component.getGroups())) {
371 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
372 if (groupOpt.isPresent()) {
373 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
374 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
376 fullName = prefix + sourceName;
378 sourceName = previousName;
381 entry.setFullName(fullName);
382 entry.setSourceName(sourceName);
383 entry.setOwner(groupOpt.get().getNormalizedName());
388 Optional<ComponentInstance> ci =
389 component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
391 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
393 Collections.reverse(path);
395 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
396 ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
399 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
400 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
401 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
402 if(buildSubstitutedName.isRight()){
403 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
406 sourceName = buildSubstitutedName.left().value();
407 fullName = prefix + sourceName;
409 sourceName = previousName;
412 entry.setFullName(fullName);
413 entry.setSourceName(sourceName);
415 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
421 private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstitutionEntry entry) {
422 Optional<ComponentInstance> findFirst = component.safeGetComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
423 findFirst.ifPresent(componentInstance -> entry.setOwner(componentInstance.getName()));
424 if (StringUtils.isNotEmpty(entry.getOwner()) && StringUtils.isNotEmpty(entry.getSourceName())) {
425 toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
429 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, String previousName, List<String> path, String ownerId, ComponentInstance instance) {
430 if(StringUtils.isNotEmpty(previousName)){
431 return Either.left(name);
433 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
434 if(getOriginRes.isRight()){
435 logger.debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid());
436 return Either.right(false);
438 List<String> reducedPath = ownerId !=null ? getReducedPathByOwner(path , ownerId ) : getReducedPath(path) ;
439 logger.debug("reducedPath for ownerId {}, reducedPath {} ", ownerId, reducedPath);
440 reducedPath.remove(reducedPath.size() - 1);
441 return buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name, previousName);
444 private String buildReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, RequirementDefinition r) {
445 return buildCapReqNamePerOwnerByPath(componentsCache, component, r.getName(), r.getPreviousName(), r.getPath());
448 private ImmutablePair<String, ToscaRequirement> convertRequirement(Map<String, Component> componentsCache, Component component, boolean isNodeType, RequirementDefinition r) {
449 String name = r.getName();
450 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
451 name = buildReqNamePerOwnerByPath(componentsCache, component, r);
453 logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
454 ToscaRequirement toscaRequirement = createToscaRequirement(r);
455 return new ImmutablePair<>(name, toscaRequirement);
458 private ToscaRequirement createToscaRequirement(RequirementDefinition r) {
459 ToscaRequirement toscaRequirement = new ToscaRequirement();
461 List<Object> occurrences = new ArrayList<>();
462 occurrences.add(Integer.valueOf(r.getMinOccurrences()));
463 if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
464 occurrences.add(r.getMaxOccurrences());
466 occurrences.add(Integer.valueOf(r.getMaxOccurrences()));
468 toscaRequirement.setOccurrences(occurrences);
469 toscaRequirement.setNode(r.getNode());
470 toscaRequirement.setCapability(r.getCapability());
471 toscaRequirement.setRelationship(r.getRelationship());
472 return toscaRequirement;
476 * Allows to convert capabilities of a node type to tosca template capabilities
481 public Map<String, ToscaCapability> convertCapabilities(Map<String, Component> componentsCache, Component component, Map<String, DataTypeDefinition> dataTypes) {
482 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
483 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
484 if (capabilities != null) {
485 boolean isNodeType = ModelConverter.isAtomicComponent(component);
486 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
487 entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapability(componentsCache, component, toscaCapabilities, isNodeType, c, dataTypes , c.getName()));
490 logger.debug(NO_CAPABILITIES);
493 return toscaCapabilities;
497 * Allows to convert capabilities of a server proxy node type to tosca template capabilities
498 * @param instanceProxy
502 public Map<String, ToscaCapability> convertProxyCapabilities(Map<String, Component> componentCache,
503 ComponentInstance instanceProxy,
504 Map<String, DataTypeDefinition> dataTypes) {
505 Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
506 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
507 if (capabilities != null) {
508 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
511 .forEach(c -> convertProxyCapability(toscaCapabilities, c, dataTypes ,
512 buildCapabilityNameForComponentInstance( componentCache , instanceProxy , c )));
515 logger.debug(NO_CAPABILITIES);
518 return toscaCapabilities;
522 * Allows to convert component capabilities to the tosca template substitution mappings capabilities
523 * @param componentsCache
527 public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache, Component component) {
528 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
529 Either<Map<String, String[]>, ToscaError> res;
530 if (capabilities != null) {
531 res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
533 res = Either.left(Maps.newHashMap());
534 logger.debug(NO_CAPABILITIES);
539 private String buildCapNamePerOwnerByPath(Map<String, Component> componentsCache, CapabilityDefinition c, Component component) {
540 return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath());
543 private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
544 Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
545 createToscaCapability(toscaCapabilities, c, dataTypes, capabilityName);
548 private void convertCapability(Map<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes , String capabilityName) {
549 String name = isNoneBlank(capabilityName) ? capabilityName : c.getName();
550 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
551 name = buildCapNamePerOwnerByPath(componentsCache, c, component);
553 logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId());
554 createToscaCapability(toscaCapabilities, c, dataTypes, name);
557 private void createToscaCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
558 Map<String, DataTypeDefinition> dataTypes, String name) {
559 ToscaCapability toscaCapability = new ToscaCapability();
560 toscaCapability.setDescription(c.getDescription());
561 toscaCapability.setType(c.getType());
563 List<Object> occurrences = new ArrayList<>();
564 occurrences.add(Integer.valueOf(c.getMinOccurrences()));
565 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
566 occurrences.add(c.getMaxOccurrences());
568 occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
570 toscaCapability.setOccurrences(occurrences);
572 toscaCapability.setValid_source_types(c.getValidSourceTypes());
573 List<ComponentInstanceProperty> properties = c.getProperties();
574 if (isNotEmpty(properties)) {
575 Map<String, ToscaProperty> toscaProperties = new HashMap<>();
576 for (PropertyDefinition property : properties) {
577 ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
578 toscaProperties.put(property.getName(), toscaProperty);
580 toscaCapability.setProperties(toscaProperties);
582 toscaCapabilities.put(name, toscaCapability);
585 private String buildCapReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path) {
586 if (CollectionUtils.isEmpty(path)) {
589 String ownerId = path.get(path.size() - 1);
591 if(CollectionUtils.isNotEmpty(component.getGroups())) {
592 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
593 if (groupOpt.isPresent()) {
594 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
595 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
596 return prefix + name;
601 Optional<ComponentInstance> ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
603 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
605 Collections.reverse(path);
607 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
608 ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
611 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
612 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
613 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
614 if(buildSubstitutedName.isRight()){
615 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
617 return prefix + buildSubstitutedName.left().value();
621 return StringUtils.EMPTY;
624 * Allows to build substituted name of capability\requirement of the origin component instance according to the path
625 * @param componentsCache
626 * @param originComponent
629 * @param previousName
632 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path, String name, String previousName) {
633 if(StringUtils.isNotEmpty(previousName)){
634 return Either.left(name);
636 StringBuilder substitutedName = new StringBuilder();
637 boolean nameBuiltSuccessfully = true;
638 if(isNotEmpty(path) && ToscaUtils.isNotComplexVfc(originComponent)){
639 List<String> reducedPath = getReducedPath(path);
640 Collections.reverse(reducedPath);
641 nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
643 return nameBuiltSuccessfully ? Either.left(substitutedName.append(name).toString()) : Either.right(nameBuiltSuccessfully);
646 protected List<String> getReducedPathByOwner(List<String> path , String ownerId) {
647 logger.debug("ownerId {}, path {} ", ownerId, path);
648 if ( CollectionUtils.isEmpty(path) ){
649 logger.debug("cannot perform reduce by owner, path to component is empty");
652 if ( isBlank(ownerId) ){
653 logger.debug("cannot perform reduce by owner, component owner is empty");
657 Map map = path.stream().collect( Collectors.toMap( it -> dropLast(it,PATH_DELIMITER) , Function.identity() , ( a , b ) -> a.endsWith(ownerId) ? a : b ));
658 //reduce list&duplicates and preserve order
659 return path.stream().distinct().filter(it -> map.values().contains(it) ).collect(Collectors.toList());
662 private List<String> getReducedPath(List<String> path) {
663 return path.stream().distinct().collect(Collectors.toList());
666 private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
667 if(isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && ToscaUtils.isNotComplexVfc(originComponent)){
668 String ownerId = instanceIdIter.next();
669 Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(ownerId)).findFirst();
670 if(instanceOpt.isPresent()){
671 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
672 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
673 if(getOriginRes.isRight()){
676 appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
677 } else if(CollectionUtils.isNotEmpty(originComponent.getGroups())){
678 Optional<GroupDefinition> groupOpt = originComponent.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
679 if(!groupOpt.isPresent()){
680 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
683 substitutedName.append(groupOpt.get().getNormalizedName()).append(PATH_DELIMITER);
685 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
692 Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
693 Either<Component, Boolean> result;
694 Either<Component, StorageOperationStatus> getOriginRes;
695 if(componentsCache.containsKey(instance.getActualComponentUid())){
696 result = Either.left(componentsCache.get(instance.getActualComponentUid()));
698 ComponentParametersView filter = getFilter(instance);
699 getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
700 if(getOriginRes.isRight()){
701 logger.debug("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
702 result = Either.right(false);
704 result = Either.left(getOriginRes.left().value());
705 componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
711 private ComponentParametersView getFilter(ComponentInstance instance) {
712 ComponentParametersView filter = new ComponentParametersView(true);
713 filter.setIgnoreComponentInstances(false);
714 if(instance.getIsProxy()){
715 filter.setIgnoreCapabilities(false);
716 filter.setIgnoreRequirements(false);
717 filter.setIgnoreCategories(false);
719 if(instance.getOriginType() == OriginTypeEnum.VF){
720 filter.setIgnoreGroups(false);