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 com.google.common.collect.Iterables;
24 import com.google.common.collect.Maps;
25 import fj.data.Either;
26 import org.apache.commons.collections.CollectionUtils;
27 import org.apache.commons.collections.MapUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
31 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
32 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
33 import org.openecomp.sdc.be.model.*;
34 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
35 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
36 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
37 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
38 import org.openecomp.sdc.be.tosca.ToscaUtils.SubstitutionEntry;
39 import org.openecomp.sdc.be.tosca.model.*;
40 import org.openecomp.sdc.common.log.wrappers.Logger;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.context.annotation.Scope;
45 import java.util.function.Function;
46 import java.util.stream.Collectors;
48 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
49 import static org.apache.commons.lang3.StringUtils.isBlank;
50 import static org.apache.commons.lang3.StringUtils.isNoneBlank;
53 * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
56 @org.springframework.stereotype.Component("capabilty-requirement-convertor")
57 @Scope(value = "singleton")
58 public class CapabilityRequirementConverter {
60 private static final String NO_CAPABILITIES = "No Capabilities for node type";
61 private static CapabilityRequirementConverter instance;
62 private static final Logger logger = Logger.getLogger(CapabilityRequirementConverter.class);
63 private static final String PATH_DELIMITER = ".";
66 private ToscaOperationFacade toscaOperationFacade;
68 public CapabilityRequirementConverter() {}
70 public static synchronized CapabilityRequirementConverter getInstance() {
71 if (instance == null) {
72 instance = new CapabilityRequirementConverter();
77 public String buildCapabilityNameForComponentInstance( Map<String,Component> componentCache , ComponentInstance componentInstance, CapabilityDefinition c) {
78 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
79 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())){
80 return buildSubstitutedName(componentCache, c.getName(), c.getPreviousName(), c.getPath(), c.getOwnerId(), componentInstance)
82 .orValue(c.getName());
84 return c.getPreviousName();
87 private String buildCapReqNamePrefix(String normalizedName) {
88 return normalizedName + PATH_DELIMITER;
92 * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
93 * @param componentInstance
98 public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilities(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
100 Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
101 Map<String,Component> componentCache = new HashMap<>();
102 if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
103 Map<String, ToscaTemplateCapability> capabilities = new HashMap<>();
104 capabilitiesInst.entrySet().forEach( e -> {
105 List<CapabilityDefinition> capList = e.getValue();
106 if ( capList != null && !capList.isEmpty() ) {
108 .forEach( c -> convertOverridenProperties( componentInstance, dataTypes, capabilities, c ,
109 buildCapabilityNameForComponentInstance( componentCache , componentInstance , c )));
112 if (MapUtils.isNotEmpty(capabilities)) {
113 nodeTemplate.setCapabilities(capabilities);
116 return Either.left(nodeTemplate);
119 private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c , String capabilityName) {
120 if (isNotEmpty(c.getProperties())) {
123 .filter(p -> p.getValue() != null || p.getDefaultValue() != null)
124 .forEach(p -> convertOverriddenProperty(componentInstance, dataTypes, capabilties , p ,capabilityName));
128 private void convertOverriddenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, ComponentInstanceProperty p , String capabilityName) {
129 if (logger.isDebugEnabled()) {
130 logger.debug("Exist d property {} for capability {} with value {}", p.getName(), capabilityName, p.getValue());
132 ToscaTemplateCapability toscaTemplateCapability = capabilties.computeIfAbsent( capabilityName , key -> new ToscaTemplateCapability() );
134 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
135 if (toscaCapProp == null) {
136 toscaCapProp = new HashMap<>();
138 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
139 toscaCapProp.put(p.getName(), convertedValue);
140 toscaTemplateCapability.setProperties(toscaCapProp);
143 private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
144 logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
145 String propertyType = prop.getType();
146 String innerType = null;
147 if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
148 innerType = prop.getSchema().getProperty().getType();
150 String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
151 return PropertyConvertor.getInstance().convertToToscaObject(propertyType, propValue, innerType, dataTypes, false);
154 * Allows to convert requirements of a node type to tosca template requirements representation
159 public Either<ToscaNodeType, ToscaError> convertRequirements(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType) {
160 List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(componentsCache, component);
161 if (!toscaRequirements.isEmpty()) {
162 nodeType.setRequirements(toscaRequirements);
164 logger.debug("Finish convert Requirements for node type");
166 return Either.left(nodeType);
170 * Allows to convert component requirements to the tosca template substitution mappings requirements
171 * @param componentsCache
173 * @param substitutionMappings
176 public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String,Component> componentsCache, Component component, SubstitutionMapping substitutionMappings) {
177 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
178 Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
179 if(toscaRequirementsRes.isRight()){
180 result = Either.right(toscaRequirementsRes.right().value());
181 logger.debug("Failed convert requirements for the component {}. ", component.getName());
182 } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
183 substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
184 result = Either.left(substitutionMappings);
185 logger.debug("Finish convert requirements for the component {}. ", component.getName());
190 private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Map<String, Component> componentsCache, Component component) {
191 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
192 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
193 if (requirements != null) {
194 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
195 entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
196 ImmutablePair<String, ToscaRequirement> pair = convertRequirement(componentsCache, component, ModelConverter.isAtomicComponent(component), r);
197 Map<String, ToscaRequirement> requirement = new HashMap<>();
199 requirement.put(pair.left, pair.right);
200 toscaRequirements.add(requirement);
202 logger.debug("Finish convert Requirements for node type");
205 logger.debug("No Requirements for node type");
207 return toscaRequirements;
210 private boolean filter(Component component, String ownerId) {
211 return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null);
214 private boolean isNodeTypeOwner(Component component, String ownerId) {
215 return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
218 private String dropLast( String path, String delimiter ) {
219 if (isBlank(path) || isBlank(delimiter)){
222 return path.substring(0, path.lastIndexOf(delimiter));
225 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
226 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
227 Either<Map<String, String[]>, ToscaError> result;
228 if (requirements != null) {
229 result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
231 result = Either.left(Maps.newHashMap());
232 logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
237 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache, Component component, Map<String, List<RequirementDefinition>> requirements) {
239 Map<String, String[]> toscaRequirements = new HashMap<>();
240 Either<Map<String, String[]>, ToscaError> result = null;
241 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
242 Optional<RequirementDefinition> failedToAddRequirement = entry.getValue()
244 .filter(r->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), r.getPreviousName(), r.getOwnerId(), r.getPath()))
246 if(failedToAddRequirement.isPresent()){
247 logger.debug("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
248 failedToAddRequirement.get().getName(), component.getName());
249 result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
251 logger.debug("Finish convert requirements for the component {}. ", component.getName());
254 result = Either.left(toscaRequirements);
259 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
261 Map<String, String[]> toscaRequirements = new HashMap<>();
262 Either<Map<String, String[]>, ToscaError> result = null;
263 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
264 Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
266 .filter(c->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath()))
268 if(failedToAddRequirement.isPresent()){
269 logger.debug("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ",
270 failedToAddRequirement.get().getName(), component.getName());
271 result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
273 logger.debug("Finish convert capalilities for the component {}. ", component.getName());
276 result = Either.left(toscaRequirements);
281 private boolean addEntry(Map<String, Component> componentsCache, Map<String, String[]> capReqMap, Component component, SubstitutionEntry entry, String previousName, String ownerId, List<String> path){
283 if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, entry.getFullName(), previousName, path, ownerId, entry)){
286 logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
287 if (entry.getSourceName() != null) {
288 addEntry(capReqMap, component, path, entry);
290 logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
295 private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
296 return ToscaUtils.isNotComplexVfc(component) && isNotEmpty(path) && path.iterator().hasNext();
299 private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path, String ownerId, SubstitutionEntry entry) {
303 if(CollectionUtils.isNotEmpty(component.getGroups())) {
304 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
305 if (groupOpt.isPresent()) {
306 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
307 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
309 fullName = prefix + sourceName;
311 sourceName = previousName;
314 entry.setFullName(fullName);
315 entry.setSourceName(sourceName);
316 entry.setOwner(groupOpt.get().getNormalizedName());
321 Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
323 logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
325 Collections.reverse(path);
327 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
328 ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
331 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
332 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
333 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
334 if(buildSubstitutedName.isRight()){
335 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
338 sourceName = buildSubstitutedName.left().value();
339 fullName = prefix + sourceName;
341 sourceName = previousName;
344 entry.setFullName(fullName);
345 entry.setSourceName(sourceName);
347 logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
353 private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstitutionEntry entry) {
354 Optional<ComponentInstance> findFirst = component.safeGetComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
355 if (findFirst.isPresent()) {
356 entry.setOwner(findFirst.get().getNormalizedName());
358 toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
361 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, String previousName, List<String> path, String ownerId, ComponentInstance instance) {
362 if(StringUtils.isNotEmpty(previousName)){
363 return Either.left(name);
365 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
366 if(getOriginRes.isRight()){
367 logger.debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid());
368 return Either.right(false);
370 List<String> reducedPath = ownerId !=null ? getReducedPathByOwner(path , ownerId ) : getReducedPath(path) ;
371 logger.debug("reducedPath for ownerId {}, reducedPath {} ", ownerId, reducedPath);
372 reducedPath.remove(reducedPath.size() - 1);
373 return buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name, previousName);
376 private String buildReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, RequirementDefinition r) {
377 return buildCapReqNamePerOwnerByPath(componentsCache, component, r.getName(), r.getPreviousName(), r.getPath());
380 private ImmutablePair<String, ToscaRequirement> convertRequirement(Map<String, Component> componentsCache, Component component, boolean isNodeType, RequirementDefinition r) {
381 String name = r.getName();
382 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
383 name = buildReqNamePerOwnerByPath(componentsCache, component, r);
385 logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
386 ToscaRequirement toscaRequirement = new ToscaRequirement();
388 List<Object> occurrences = new ArrayList<>();
389 occurrences.add(Integer.valueOf(r.getMinOccurrences()));
390 if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
391 occurrences.add(r.getMaxOccurrences());
393 occurrences.add(Integer.valueOf(r.getMaxOccurrences()));
395 toscaRequirement.setOccurrences(occurrences);
396 toscaRequirement.setNode(r.getNode());
397 toscaRequirement.setCapability(r.getCapability());
398 toscaRequirement.setRelationship(r.getRelationship());
400 return new ImmutablePair<>(name, toscaRequirement);
404 * Allows to convert capabilities of a node type to tosca template capabilities
409 public Map<String, ToscaCapability> convertCapabilities(Map<String, Component> componentsCache, Component component, Map<String, DataTypeDefinition> dataTypes) {
410 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
411 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
412 if (capabilities != null) {
413 boolean isNodeType = ModelConverter.isAtomicComponent(component);
414 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
415 entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapability(componentsCache, component, toscaCapabilities, isNodeType, c, dataTypes , c.getName()));
418 logger.debug(NO_CAPABILITIES);
421 return toscaCapabilities;
425 * Allows to convert capabilities of a server proxy node type to tosca template capabilities
427 * @param proxyComponent
428 * @param instanceProxy
432 public Map<String, ToscaCapability> convertProxyCapabilities(Map<String, Component> componentCache, Component component, Component proxyComponent, ComponentInstance instanceProxy, Map<String, DataTypeDefinition> dataTypes) {
433 Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
434 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
435 if (capabilities != null) {
436 boolean isNodeType = ModelConverter.isAtomicComponent(component);
437 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
440 .forEach(c -> convertProxyCapability(toscaCapabilities, c, dataTypes ,
441 buildCapabilityNameForComponentInstance( componentCache , instanceProxy , c )));
444 logger.debug(NO_CAPABILITIES);
447 return toscaCapabilities;
451 * Allows to convert component capabilities to the tosca template substitution mappings capabilities
452 * @param componentsCache
456 public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache, Component component) {
457 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
458 Either<Map<String, String[]>, ToscaError> res;
459 if (capabilities != null) {
460 res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
462 res = Either.left(Maps.newHashMap());
463 logger.debug(NO_CAPABILITIES);
468 private String buildCapNamePerOwnerByPath(Map<String, Component> componentsCache, CapabilityDefinition c, Component component) {
469 return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath());
472 private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
473 ToscaCapability toscaCapability = new ToscaCapability();
474 toscaCapability.setDescription(c.getDescription());
475 toscaCapability.setType(c.getType());
477 List<Object> occurrences = new ArrayList<>();
478 occurrences.add(Integer.valueOf(c.getMinOccurrences()));
479 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
480 occurrences.add(c.getMaxOccurrences());
482 occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
484 toscaCapability.setOccurrences(occurrences);
486 toscaCapability.setValid_source_types(c.getValidSourceTypes());
487 List<ComponentInstanceProperty> properties = c.getProperties();
488 if (isNotEmpty(properties)) {
489 Map<String, ToscaProperty> toscaProperties = new HashMap<>();
490 for (PropertyDefinition property : properties) {
491 ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
492 toscaProperties.put(property.getName(), toscaProperty);
494 toscaCapability.setProperties(toscaProperties);
496 toscaCapabilities.put(capabilityName, toscaCapability);
499 private void convertCapability(Map<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes , String capabilityName) {
500 String name = isNoneBlank(capabilityName) ? capabilityName : c.getName();
501 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
502 name = buildCapNamePerOwnerByPath(componentsCache, c, component);
504 logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId());
505 ToscaCapability toscaCapability = new ToscaCapability();
506 toscaCapability.setDescription(c.getDescription());
507 toscaCapability.setType(c.getType());
509 List<Object> occurrences = new ArrayList<>();
510 occurrences.add(Integer.valueOf(c.getMinOccurrences()));
511 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
512 occurrences.add(c.getMaxOccurrences());
514 occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
516 toscaCapability.setOccurrences(occurrences);
518 toscaCapability.setValid_source_types(c.getValidSourceTypes());
519 List<ComponentInstanceProperty> properties = c.getProperties();
520 if (isNotEmpty(properties)) {
521 Map<String, ToscaProperty> toscaProperties = new HashMap<>();
522 for (PropertyDefinition property : properties) {
523 ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
524 toscaProperties.put(property.getName(), toscaProperty);
526 toscaCapability.setProperties(toscaProperties);
528 toscaCapabilities.put(name, toscaCapability);
531 private String buildCapReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path) {
532 String ownerId = path.get(path.size() - 1);
534 if(CollectionUtils.isNotEmpty(component.getGroups())) {
535 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
536 if (groupOpt.isPresent()) {
537 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
538 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
539 return prefix + name;
544 Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
546 logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
548 Collections.reverse(path);
550 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
551 ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
554 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
555 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
556 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
557 if(buildSubstitutedName.isRight()){
558 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
560 return prefix + buildSubstitutedName.left().value();
564 return StringUtils.EMPTY;
567 * Allows to build substituted name of capability\requirement of the origin component instance according to the path
568 * @param componentsCache
569 * @param originComponent
572 * @param previousName
575 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path, String name, String previousName) {
576 if(StringUtils.isNotEmpty(previousName)){
577 return Either.left(name);
579 StringBuilder substitutedName = new StringBuilder();
580 boolean nameBuiltSuccessfully = true;
581 if(isNotEmpty(path) && ToscaUtils.isNotComplexVfc(originComponent)){
582 List<String> reducedPath = getReducedPath(path);
583 Collections.reverse(reducedPath);
584 nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
586 return nameBuiltSuccessfully ? Either.left(substitutedName.append(name).toString()) : Either.right(nameBuiltSuccessfully);
589 protected List<String> getReducedPathByOwner(List<String> path , String ownerId) {
590 logger.debug("ownerId {}, path {} ", ownerId, path);
591 if ( CollectionUtils.isEmpty(path) ){
592 logger.debug("cannot perform reduce by owner, path to component is empty");
595 if ( isBlank(ownerId) ){
596 logger.debug("cannot perform reduce by owner, component owner is empty");
600 Map map = path.stream().collect( Collectors.toMap( it -> dropLast(it,PATH_DELIMITER) , Function.identity() , ( a , b ) -> a.endsWith(ownerId) ? a : b ));
601 //reduce list&duplicates and preserve order
602 return path.stream().distinct().filter(it -> map.values().contains(it) ).collect(Collectors.toList());
605 private List<String> getReducedPath(List<String> path) {
606 return path.stream().distinct().collect(Collectors.toList());
609 private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
610 if(isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && ToscaUtils.isNotComplexVfc(originComponent)){
611 String ownerId = instanceIdIter.next();
612 Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(ownerId)).findFirst();
613 if(instanceOpt.isPresent()){
614 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
615 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
616 if(getOriginRes.isRight()){
619 appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
620 } else if(CollectionUtils.isNotEmpty(originComponent.getGroups())){
621 Optional<GroupDefinition> groupOpt = originComponent.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
622 if(!groupOpt.isPresent()){
623 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
626 substitutedName.append(groupOpt.get().getNormalizedName()).append(PATH_DELIMITER);
628 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
635 Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
636 Either<Component, Boolean> result;
637 Either<Component, StorageOperationStatus> getOriginRes;
638 if(componentsCache.containsKey(instance.getActualComponentUid())){
639 result = Either.left(componentsCache.get(instance.getActualComponentUid()));
641 ComponentParametersView filter = getFilter(instance);
642 getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
643 if(getOriginRes.isRight()){
644 logger.debug("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
645 result = Either.right(false);
647 result = Either.left(getOriginRes.left().value());
648 componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
654 private ComponentParametersView getFilter(ComponentInstance instance) {
655 ComponentParametersView filter = new ComponentParametersView(true);
656 filter.setIgnoreComponentInstances(false);
657 if(instance.getIsProxy()){
658 filter.setIgnoreCapabilities(false);
659 filter.setIgnoreRequirements(false);
660 filter.setIgnoreCategories(false);
662 if(instance.getOriginType() == OriginTypeEnum.VF){
663 filter.setIgnoreGroups(false);