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.CapabilityDefinition;
34 import org.openecomp.sdc.be.model.Component;
35 import org.openecomp.sdc.be.model.ComponentInstance;
36 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
37 import org.openecomp.sdc.be.model.ComponentParametersView;
38 import org.openecomp.sdc.be.model.DataTypeDefinition;
39 import org.openecomp.sdc.be.model.GroupDefinition;
40 import org.openecomp.sdc.be.model.PropertyDefinition;
41 import org.openecomp.sdc.be.model.RequirementDefinition;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
44 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
45 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
46 import org.openecomp.sdc.be.tosca.ToscaUtils.SubstitutionEntry;
47 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
48 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
49 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
50 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
51 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
52 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
53 import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
54 import org.openecomp.sdc.common.log.wrappers.Logger;
55 import org.springframework.beans.factory.annotation.Autowired;
56 import org.springframework.context.annotation.Scope;
58 import java.util.ArrayList;
59 import java.util.Collections;
60 import java.util.HashMap;
61 import java.util.Iterator;
62 import java.util.List;
64 import java.util.Optional;
65 import java.util.function.Function;
66 import java.util.stream.Collectors;
68 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
69 import static org.apache.commons.lang3.StringUtils.isBlank;
70 import static org.apache.commons.lang3.StringUtils.isNoneBlank;
73 * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
76 @org.springframework.stereotype.Component("capabilty-requirement-convertor")
77 @Scope(value = "singleton")
78 public class CapabilityRequirementConverter {
80 private static final String NO_CAPABILITIES = "No Capabilities for node type";
81 private static final String NO_REQUIREMENTS = "No Requirements for node type";
82 private static CapabilityRequirementConverter instance;
83 private static final Logger logger = Logger.getLogger(CapabilityRequirementConverter.class);
84 private static final String PATH_DELIMITER = ".";
85 private static final String FAILED_TO_FIND_CI_IN_PATH ="Failed to find ci in the path is {} component {}";
88 private ToscaOperationFacade toscaOperationFacade;
90 public CapabilityRequirementConverter() {}
92 public static synchronized CapabilityRequirementConverter getInstance() {
93 if (instance == null) {
94 instance = new CapabilityRequirementConverter();
99 public String buildCapabilityNameForComponentInstance( Map<String,Component> componentCache , ComponentInstance componentInstance, CapabilityDefinition c) {
100 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
101 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())){
102 return buildSubstitutedName(componentCache, c.getName(), c.getPreviousName(), c.getPath(), c.getOwnerId(), componentInstance)
104 .orValue(c.getName());
106 return c.getPreviousName();
109 public String buildRequirementNameForComponentInstance(Map<String,Component> componentCache,
110 ComponentInstance componentInstance,
111 RequirementDefinition r) {
112 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
113 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
114 return buildSubstitutedName(componentCache, r.getName(), r.getPreviousName(), r.getPath(), r.getOwnerId(),
115 componentInstance).left()
116 .orValue(r.getName());
118 return r.getPreviousName();
121 private String buildCapReqNamePrefix(String normalizedName) {
122 return normalizedName + PATH_DELIMITER;
126 * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
127 * @param componentInstance
129 * @param nodeTemplate
132 public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilities(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
134 Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
135 Map<String,Component> componentCache = new HashMap<>();
136 if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
137 Map<String, ToscaTemplateCapability> capabilities = new HashMap<>();
138 capabilitiesInst.entrySet().forEach( e -> {
139 List<CapabilityDefinition> capList = e.getValue();
140 if ( capList != null && !capList.isEmpty() ) {
142 .forEach( c -> convertOverridenProperties( componentInstance, dataTypes, capabilities, c ,
143 buildCapabilityNameForComponentInstance( componentCache , componentInstance , c )));
146 if (MapUtils.isNotEmpty(capabilities)) {
147 nodeTemplate.setCapabilities(capabilities);
150 return Either.left(nodeTemplate);
153 private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c , String capabilityName) {
154 if (isNotEmpty(c.getProperties())) {
157 .filter(p -> p.getValue() != null || p.getDefaultValue() != null)
158 .forEach(p -> convertOverriddenProperty(componentInstance, dataTypes, capabilties , p ,capabilityName));
162 private void convertOverriddenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, ComponentInstanceProperty p , String capabilityName) {
163 if (logger.isDebugEnabled()) {
164 logger.debug("Exist d property {} for capability {} with value {}", p.getName(), capabilityName, p.getValue());
166 ToscaTemplateCapability toscaTemplateCapability = capabilties.computeIfAbsent( capabilityName , key -> new ToscaTemplateCapability() );
168 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
169 if (toscaCapProp == null) {
170 toscaCapProp = new HashMap<>();
172 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
173 toscaCapProp.put(p.getName(), convertedValue);
174 toscaTemplateCapability.setProperties(toscaCapProp);
177 private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
178 logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
179 String propertyType = prop.getType();
180 String innerType = null;
181 if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
182 innerType = prop.getSchema().getProperty().getType();
184 String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
185 return PropertyConvertor.getInstance().convertToToscaObject(propertyType, propValue, innerType, dataTypes, false);
188 * Allows to convert requirements of a node type to tosca template requirements representation
193 public Either<ToscaNodeType, ToscaError> convertRequirements(Map<String, Component> componentsCache, Component component, ToscaNodeType nodeType) {
194 List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(componentsCache, component);
195 if (!toscaRequirements.isEmpty()) {
196 nodeType.setRequirements(toscaRequirements);
198 logger.debug("Finish convert Requirements for node type");
200 return Either.left(nodeType);
204 * Allows to convert component requirements to the tosca template substitution mappings requirements
205 * @param componentsCache
207 * @param substitutionMappings
210 public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String,Component> componentsCache, Component component, SubstitutionMapping substitutionMappings) {
211 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
212 Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
213 if(toscaRequirementsRes.isRight()){
214 result = Either.right(toscaRequirementsRes.right().value());
215 logger.debug("Failed convert requirements for the component {}. ", component.getName());
216 } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
217 substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
218 result = Either.left(substitutionMappings);
219 logger.debug("Finish convert requirements for the component {}. ", component.getName());
225 * Allows to convert requirements of a server proxy node type to tosca template requirements
226 * @param instanceProxy
227 * @return converted tosca template requirements
229 List<Map<String, ToscaRequirement>> convertProxyRequirements(Map<String, Component> componentCache,
230 ComponentInstance instanceProxy) {
231 Map<String, List<RequirementDefinition>> requirements = instanceProxy.getRequirements();
232 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
233 if (requirements != null) {
234 requirements.entrySet().stream()
235 .flatMap(e -> e.getValue().stream())
237 ImmutablePair<String, ToscaRequirement> pair = convertProxyRequirement(
238 buildRequirementNameForComponentInstance(componentCache, instanceProxy, req), req);
239 Map<String, ToscaRequirement> requirement = new HashMap<>();
240 requirement.put(pair.left, pair.right);
241 toscaRequirements.add(requirement);
244 logger.debug(NO_REQUIREMENTS);
247 return toscaRequirements;
250 private ImmutablePair<String, ToscaRequirement> convertProxyRequirement(String requirementName,
251 RequirementDefinition r) {
252 ToscaRequirement toscaRequirement = createToscaRequirement(r);
253 return new ImmutablePair<>(requirementName, toscaRequirement);
256 private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Map<String, Component> componentsCache, Component component) {
257 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
258 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
259 if (requirements != null) {
260 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
261 entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
262 ImmutablePair<String, ToscaRequirement> pair = convertRequirement(componentsCache, component, ModelConverter.isAtomicComponent(component), r);
263 Map<String, ToscaRequirement> requirement = new HashMap<>();
265 requirement.put(pair.left, pair.right);
266 toscaRequirements.add(requirement);
268 logger.debug("Finish convert Requirements for node type");
271 logger.debug(NO_REQUIREMENTS);
273 return toscaRequirements;
276 private boolean filter(Component component, String ownerId) {
277 return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null);
280 private boolean isNodeTypeOwner(Component component, String ownerId) {
281 return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
284 private String dropLast( String path, String delimiter ) {
285 if (isBlank(path) || isBlank(delimiter)){
288 return path.substring(0, path.lastIndexOf(delimiter));
291 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
292 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
293 Either<Map<String, String[]>, ToscaError> result;
294 if (requirements != null) {
295 result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
297 result = Either.left(Maps.newHashMap());
298 logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
303 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache, Component component, Map<String, List<RequirementDefinition>> requirements) {
305 Map<String, String[]> toscaRequirements = new HashMap<>();
306 Either<Map<String, String[]>, ToscaError> result = null;
307 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
308 Optional<RequirementDefinition> failedToAddRequirement = entry.getValue()
310 .filter(r->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), r.getPreviousName(), r.getOwnerId(), r.getPath()))
312 if(failedToAddRequirement.isPresent()){
313 logger.debug("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
314 failedToAddRequirement.get().getName(), component.getName());
315 result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
317 logger.debug("Finish convert requirements for the component {}. ", component.getName());
320 result = Either.left(toscaRequirements);
325 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
327 Map<String, String[]> toscaCapabilities = new HashMap<>();
328 Either<Map<String, String[]>, ToscaError> result = null;
329 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
330 Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
332 .filter(c->!addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath()))
334 if(failedToAddRequirement.isPresent()){
335 logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ",
336 failedToAddRequirement.get().getName(), component.getName());
337 result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
339 logger.debug("Finish convert capabilities for the component {}. ", component.getName());
342 result = Either.left(toscaCapabilities);
347 private boolean addEntry(Map<String, Component> componentsCache, Map<String, String[]> capReqMap, Component component, SubstitutionEntry entry, String previousName, String ownerId, List<String> path){
349 if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, entry.getFullName(), previousName, path, ownerId, entry)){
352 logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
353 if (StringUtils.isNotEmpty(entry.getSourceName())) {
354 addEntry(capReqMap, component, path, entry);
356 logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
361 private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
362 return ToscaUtils.isNotComplexVfc(component) && isNotEmpty(path) && path.iterator().hasNext();
365 private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path, String ownerId, SubstitutionEntry entry) {
369 if(CollectionUtils.isNotEmpty(component.getGroups())) {
370 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
371 if (groupOpt.isPresent()) {
372 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
373 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
375 fullName = prefix + sourceName;
377 sourceName = previousName;
380 entry.setFullName(fullName);
381 entry.setSourceName(sourceName);
382 entry.setOwner(groupOpt.get().getNormalizedName());
387 Optional<ComponentInstance> ci =
388 component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
390 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
392 Collections.reverse(path);
394 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
395 ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
398 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
399 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
400 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
401 if(buildSubstitutedName.isRight()){
402 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
405 sourceName = buildSubstitutedName.left().value();
406 fullName = prefix + sourceName;
408 sourceName = previousName;
411 entry.setFullName(fullName);
412 entry.setSourceName(sourceName);
414 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
420 private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstitutionEntry entry) {
421 Optional<ComponentInstance> findFirst = component.safeGetComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
422 findFirst.ifPresent(componentInstance -> entry.setOwner(componentInstance.getName()));
423 if (StringUtils.isNotEmpty(entry.getOwner()) && StringUtils.isNotEmpty(entry.getSourceName())) {
424 toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
428 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, String previousName, List<String> path, String ownerId, ComponentInstance instance) {
429 if(StringUtils.isNotEmpty(previousName)){
430 return Either.left(name);
432 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
433 if(getOriginRes.isRight()){
434 logger.debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid());
435 return Either.right(false);
437 List<String> reducedPath = ownerId !=null ? getReducedPathByOwner(path , ownerId ) : getReducedPath(path) ;
438 logger.debug("reducedPath for ownerId {}, reducedPath {} ", ownerId, reducedPath);
439 reducedPath.remove(reducedPath.size() - 1);
440 return buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name, previousName);
443 private String buildReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, RequirementDefinition r) {
444 return buildCapReqNamePerOwnerByPath(componentsCache, component, r.getName(), r.getPreviousName(), r.getPath());
447 private ImmutablePair<String, ToscaRequirement> convertRequirement(Map<String, Component> componentsCache, Component component, boolean isNodeType, RequirementDefinition r) {
448 String name = r.getName();
449 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
450 name = buildReqNamePerOwnerByPath(componentsCache, component, r);
452 logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
453 ToscaRequirement toscaRequirement = createToscaRequirement(r);
454 return new ImmutablePair<>(name, toscaRequirement);
457 private ToscaRequirement createToscaRequirement(RequirementDefinition r) {
458 ToscaRequirement toscaRequirement = new ToscaRequirement();
460 List<Object> occurrences = new ArrayList<>();
461 occurrences.add(Integer.valueOf(r.getMinOccurrences()));
462 if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
463 occurrences.add(r.getMaxOccurrences());
465 occurrences.add(Integer.valueOf(r.getMaxOccurrences()));
467 toscaRequirement.setOccurrences(occurrences);
468 toscaRequirement.setNode(r.getNode());
469 toscaRequirement.setCapability(r.getCapability());
470 toscaRequirement.setRelationship(r.getRelationship());
471 return toscaRequirement;
475 * Allows to convert capabilities of a node type to tosca template capabilities
480 public Map<String, ToscaCapability> convertCapabilities(Map<String, Component> componentsCache, Component component, Map<String, DataTypeDefinition> dataTypes) {
481 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
482 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
483 if (capabilities != null) {
484 boolean isNodeType = ModelConverter.isAtomicComponent(component);
485 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
486 entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapability(componentsCache, component, toscaCapabilities, isNodeType, c, dataTypes , c.getName()));
489 logger.debug(NO_CAPABILITIES);
492 return toscaCapabilities;
496 * Allows to convert capabilities of a server proxy node type to tosca template capabilities
497 * @param instanceProxy
501 public Map<String, ToscaCapability> convertProxyCapabilities(Map<String, Component> componentCache,
502 ComponentInstance instanceProxy,
503 Map<String, DataTypeDefinition> dataTypes) {
504 Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
505 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
506 if (capabilities != null) {
507 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
510 .forEach(c -> convertProxyCapability(toscaCapabilities, c, dataTypes ,
511 buildCapabilityNameForComponentInstance( componentCache , instanceProxy , c )));
514 logger.debug(NO_CAPABILITIES);
517 return toscaCapabilities;
521 * Allows to convert component capabilities to the tosca template substitution mappings capabilities
522 * @param componentsCache
526 public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache, Component component) {
527 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
528 Either<Map<String, String[]>, ToscaError> res;
529 if (capabilities != null) {
530 res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
532 res = Either.left(Maps.newHashMap());
533 logger.debug(NO_CAPABILITIES);
538 private String buildCapNamePerOwnerByPath(Map<String, Component> componentsCache, CapabilityDefinition c, Component component) {
539 return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath());
542 private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
543 Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
544 createToscaCapability(toscaCapabilities, c, dataTypes, capabilityName);
547 private void convertCapability(Map<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes , String capabilityName) {
548 String name = isNoneBlank(capabilityName) ? capabilityName : c.getName();
549 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
550 name = buildCapNamePerOwnerByPath(componentsCache, c, component);
552 logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId());
553 createToscaCapability(toscaCapabilities, c, dataTypes, name);
556 private void createToscaCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
557 Map<String, DataTypeDefinition> dataTypes, String name) {
558 ToscaCapability toscaCapability = new ToscaCapability();
559 toscaCapability.setDescription(c.getDescription());
560 toscaCapability.setType(c.getType());
562 List<Object> occurrences = new ArrayList<>();
563 occurrences.add(Integer.valueOf(c.getMinOccurrences()));
564 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
565 occurrences.add(c.getMaxOccurrences());
567 occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
569 toscaCapability.setOccurrences(occurrences);
571 toscaCapability.setValid_source_types(c.getValidSourceTypes());
572 List<ComponentInstanceProperty> properties = c.getProperties();
573 if (isNotEmpty(properties)) {
574 Map<String, ToscaProperty> toscaProperties = new HashMap<>();
575 for (PropertyDefinition property : properties) {
576 ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
577 toscaProperties.put(property.getName(), toscaProperty);
579 toscaCapability.setProperties(toscaProperties);
581 toscaCapabilities.put(name, toscaCapability);
584 private String buildCapReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path) {
585 if (CollectionUtils.isEmpty(path)) {
588 String ownerId = path.get(path.size() - 1);
590 if(CollectionUtils.isNotEmpty(component.getGroups())) {
591 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
592 if (groupOpt.isPresent()) {
593 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
594 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
595 return prefix + name;
600 Optional<ComponentInstance> ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
602 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
604 Collections.reverse(path);
606 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
607 ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
610 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
611 if(ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)){
612 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
613 if(buildSubstitutedName.isRight()){
614 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
616 return prefix + buildSubstitutedName.left().value();
620 return StringUtils.EMPTY;
623 * Allows to build substituted name of capability\requirement of the origin component instance according to the path
624 * @param componentsCache
625 * @param originComponent
628 * @param previousName
631 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path, String name, String previousName) {
632 if(StringUtils.isNotEmpty(previousName)){
633 return Either.left(name);
635 StringBuilder substitutedName = new StringBuilder();
636 boolean nameBuiltSuccessfully = true;
637 if(isNotEmpty(path) && ToscaUtils.isNotComplexVfc(originComponent)){
638 List<String> reducedPath = getReducedPath(path);
639 Collections.reverse(reducedPath);
640 nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
642 return nameBuiltSuccessfully ? Either.left(substitutedName.append(name).toString()) : Either.right(nameBuiltSuccessfully);
645 protected List<String> getReducedPathByOwner(List<String> path , String ownerId) {
646 logger.debug("ownerId {}, path {} ", ownerId, path);
647 if ( CollectionUtils.isEmpty(path) ){
648 logger.debug("cannot perform reduce by owner, path to component is empty");
651 if ( isBlank(ownerId) ){
652 logger.debug("cannot perform reduce by owner, component owner is empty");
656 Map map = path.stream().collect( Collectors.toMap( it -> dropLast(it,PATH_DELIMITER) , Function.identity() , ( a , b ) -> a.endsWith(ownerId) ? a : b ));
657 //reduce list&duplicates and preserve order
658 return path.stream().distinct().filter(it -> map.values().contains(it) ).collect(Collectors.toList());
661 private List<String> getReducedPath(List<String> path) {
662 return path.stream().distinct().collect(Collectors.toList());
665 private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
666 if(isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && ToscaUtils.isNotComplexVfc(originComponent)){
667 String ownerId = instanceIdIter.next();
668 Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(ownerId)).findFirst();
669 if(instanceOpt.isPresent()){
670 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
671 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
672 if(getOriginRes.isRight()){
675 appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
676 } else if(CollectionUtils.isNotEmpty(originComponent.getGroups())){
677 Optional<GroupDefinition> groupOpt = originComponent.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
678 if(!groupOpt.isPresent()){
679 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
682 substitutedName.append(groupOpt.get().getNormalizedName()).append(PATH_DELIMITER);
684 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
691 Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
692 Either<Component, Boolean> result;
693 Either<Component, StorageOperationStatus> getOriginRes;
694 if(componentsCache.containsKey(instance.getActualComponentUid())){
695 result = Either.left(componentsCache.get(instance.getActualComponentUid()));
697 ComponentParametersView filter = getFilter(instance);
698 getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
699 if(getOriginRes.isRight()){
700 logger.debug("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
701 result = Either.right(false);
703 result = Either.left(getOriginRes.left().value());
704 componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
710 private ComponentParametersView getFilter(ComponentInstance instance) {
711 ComponentParametersView filter = new ComponentParametersView(true);
712 filter.setIgnoreComponentInstances(false);
713 if(instance.getIsProxy()){
714 filter.setIgnoreCapabilities(false);
715 filter.setIgnoreRequirements(false);
716 filter.setIgnoreCategories(false);
718 if(instance.getOriginType() == OriginTypeEnum.VF){
719 filter.setIgnoreGroups(false);