From bd5a1006210092f9ac5c48352cc94f6264e961ef Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Wed, 18 Nov 2020 18:13:58 +0000 Subject: Initial support for relationship_templates Change-Id: Ia246b9f11a77815c0585abfa0b3de5433728001a Issue-ID: SDC-3435 Signed-off-by: andre.schmid --- .../sdc/be/exception/ToscaExportException.java | 28 ++ .../be/tosca/InterfacesOperationsConverter.java | 26 +- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 385 +++++++++++++-------- .../ToscaExportRelationshipTemplatesHandler.java | 83 +++++ .../be/tosca/builder/ToscaRelationshipBuilder.java | 71 ++++ .../be/tosca/model/ToscaOperationAssignment.java | 34 ++ .../be/tosca/model/ToscaPropertyAssignment.java | 31 ++ .../sdc/be/tosca/model/ToscaRelationship.java | 35 ++ .../be/tosca/model/ToscaRelationshipTemplate.java | 40 +++ .../sdc/be/tosca/model/ToscaRequirement.java | 20 +- .../be/tosca/model/ToscaTemplateRequirement.java | 70 ++-- .../sdc/be/tosca/model/ToscaTopolgyTemplate.java | 41 +-- .../sdc/be/tosca/utils/InterfaceTypesNameUtil.java | 43 +++ 13 files changed, 682 insertions(+), 225 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/exception/ToscaExportException.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportRelationshipTemplatesHandler.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaOperationAssignment.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignment.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationship.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationshipTemplate.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfaceTypesNameUtil.java (limited to 'catalog-be/src/main/java/org') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/exception/ToscaExportException.java b/catalog-be/src/main/java/org/openecomp/sdc/be/exception/ToscaExportException.java new file mode 100644 index 0000000000..66357c118e --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/exception/ToscaExportException.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.exception; + +public class ToscaExportException extends Exception { + + public ToscaExportException(String message) { + super(message); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java index 1f1dcfed8c..8fb835e0b9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; @@ -155,12 +157,15 @@ public class InterfacesOperationsConverter { Map toscaInterfaceDefinitions = new HashMap<>(); for (InterfaceDefinition interfaceDefinition : interfaces.values()) { ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition(); - String interfaceType; + final String interfaceType; if(componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) { interfaceType = DERIVED_FROM_BASE_DEFAULT + componentInstance.getSourceModelName(); } else { interfaceType = getInterfaceType(component, interfaceDefinition.getType()); } + if (componentInstance == null) { + toscaInterfaceDefinition.setType(interfaceType); + } toscaInterfaceDefinition.setType(interfaceType); final Map operations = interfaceDefinition.getOperations(); Map toscaOperationMap = new HashMap<>(); @@ -204,6 +209,25 @@ public class InterfacesOperationsConverter { return toscaInterfaceDefinitions; } + public void removeInterfacesWithoutOperations(final Map interfaceMap) { + if (MapUtils.isEmpty(interfaceMap)) { + return; + } + final Set emptyInterfaces = interfaceMap.entrySet().stream() + .filter(entry -> { + final Object value = entry.getValue(); + if (value instanceof ToscaInterfaceDefinition) { + final ToscaInterfaceDefinition interfaceDefinition = (ToscaInterfaceDefinition) value; + return MapUtils.isEmpty(interfaceDefinition.getOperations()); + } else if (value instanceof Map) { + final Map interfaceDefMap = (Map) value; + return MapUtils.isEmpty(interfaceDefMap); + } + return false; + }).map(Entry::getKey).collect(Collectors.toSet()); + emptyInterfaces.forEach(interfaceMap::remove); + } + private Map createInterfaceInputMap(final InterfaceDefinition interfaceDefinition, final Map allDataTypeMap) { final Map inputMap = interfaceDefinition.getInputs(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 6131eb5850..b8da23085d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -20,17 +20,20 @@ package org.openecomp.sdc.be.tosca; -import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.collections.MapUtils.isNotEmpty; import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput; import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import fj.data.Either; import java.beans.IntrospectionException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -71,8 +74,10 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.exception.ToscaExportException; import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceInput; @@ -95,7 +100,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; -import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; +import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder; import org.openecomp.sdc.be.tosca.model.CapabilityFilter; import org.openecomp.sdc.be.tosca.model.NodeFilter; import org.openecomp.sdc.be.tosca.model.SubstitutionMapping; @@ -107,6 +112,8 @@ import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate; import org.openecomp.sdc.be.tosca.model.ToscaNodeType; import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate; import org.openecomp.sdc.be.tosca.model.ToscaProperty; +import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment; +import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate; import org.openecomp.sdc.be.tosca.model.ToscaRequirement; import org.openecomp.sdc.be.tosca.model.ToscaTemplate; import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact; @@ -330,6 +337,12 @@ public class ToscaExportHandler { log.debug("node templates converted"); topologyTemplate.setNode_templates(nodeTemplates.left().value()); } + final Map relationshipTemplatesMap = + new ToscaExportRelationshipTemplatesHandler() + .createFrom(topologyTemplate.getNode_templates()); + if (!relationshipTemplatesMap.isEmpty()) { + topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap); + } SubstitutionMapping substitutionMapping = new SubstitutionMapping(); convertSubstitutionMappingFilter(component, substitutionMapping); @@ -950,30 +963,31 @@ public class ToscaExportHandler { String instanceUniqueId, Component parentComponent) { - Map interfaces; - + final Map interfaceMap; // we need to handle service proxy interfaces if (isComponentOfTypeServiceProxy(componentInstance)) { if (MapUtils.isEmpty(componentInstanceInterfaces) || !componentInstanceInterfaces.containsKey(instanceUniqueId)) { - interfaces = null; - } else { - List currServiceInterfaces = - componentInstanceInterfaces.get(instanceUniqueId); + nodeTemplate.setInterfaces(null); + return; + } - Map tmpInterfaces = new HashMap<>(); - currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface - .getUniqueId(), instInterface)); + final List currServiceInterfaces = + componentInstanceInterfaces.get(instanceUniqueId); - interfaces = interfacesOperationsConverter - .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, true, true); - } + final Map tmpInterfaces = new HashMap<>(); + currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface + .getUniqueId(), instInterface)); + + interfaceMap = interfacesOperationsConverter + .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, true, true); } else { - interfaces = + interfaceMap = getComponentInstanceInterfaceInstances(componentInstanceInterfaces, componentInstance, instanceUniqueId); } - nodeTemplate.setInterfaces(interfaces); + interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); + nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); } private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) { @@ -1050,30 +1064,6 @@ public class ToscaExportHandler { } } - /** - * - */ - private void convertAndAddValue(Map dataTypes, ComponentInstance componentInstance, - Map props, PropertyDefinition prop, Supplier supplier) { - Object convertedValue = convertValue(dataTypes, componentInstance, prop, supplier); - if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) { - props.put(prop.getName(), convertedValue); - } - } - - private Object convertValue(Map dataTypes, - ComponentInstance componentInstance, T input, - Supplier supplier) { - log.debug("Convert property or input value {} for instance {}", input.getName(), - componentInstance.getUniqueId()); - String propertyType = input.getType(); - String innerType = null; - if (input.getSchema() != null && input.getSchema().getProperty() != null) { - innerType = input.getSchema().getProperty().getType(); - } - return propertyConvertor.convertToToscaObject(input, supplier.get(), dataTypes, true); - } - private ToscaNodeType createNodeType(Component component) { ToscaNodeType toscaNodeType = new ToscaNodeType(); if (ModelConverter.isAtomicComponent(component)) { @@ -1265,7 +1255,11 @@ public class ToscaExportHandler { proxyProperties.ifPresent(toscaNodeType::setProperties); Optional> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); - proxyInterfaces.ifPresent(toscaNodeType::setInterfaces); + if (proxyInterfaces.isPresent()) { + final Map interfaceMap = proxyInterfaces.get(); + interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); + toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); + } return toscaNodeType; } @@ -1277,92 +1271,110 @@ public class ToscaExportHandler { Component originComponent, Map componentCache) { - List> toscaRequirements = new ArrayList<>(); - if (!addRequirements(component, componentInstance, relations, originComponent, toscaRequirements, - componentCache)) { - log.debug("Failed to convert component instance requirements for the component instance {}. ", - componentInstance.getName()); - return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); - } - if (!toscaRequirements.isEmpty()) { - nodeTypeTemplate.setRequirements(toscaRequirements); + final List> toscaRequirements; + final List requirementDefinitionList = filterRequirements(componentInstance, + relations); + if (isNotEmpty(requirementDefinitionList)) { + try { + toscaRequirements = buildRequirements(component, componentInstance, + requirementDefinitionList, originComponent, componentCache); + if (!toscaRequirements.isEmpty()) { + nodeTypeTemplate.setRequirements(toscaRequirements); + } + } catch (final Exception e) { + log.debug("Failed to convert component instance requirements for the component instance {}. ", + componentInstance.getName(), e); + return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); + } } log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName()); return Either.left(nodeTypeTemplate); } - private boolean addRequirements(Component component, ComponentInstance componentInstance, - List relations, Component originComponent, - List> toscaRequirements, - Map componentCache) { - List filteredRelations = relations.stream() + private List> buildRequirements(final Component component, + final ComponentInstance componentInstance, + final List filteredRelations, + final Component originComponent, + final Map componentCache) + throws ToscaExportException { + + final List> toscaRequirements = new ArrayList<>(); + for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) { + final Map toscaTemplateRequirementMap = + buildRequirement(componentInstance, originComponent, component.getComponentInstances(), + relationshipDefinition, componentCache); + toscaRequirements.add(toscaTemplateRequirementMap); + } + + return toscaRequirements; + } + + private List filterRequirements(ComponentInstance componentInstance, + List relations) { + return relations.stream() .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList()); - return isEmpty(filteredRelations) || - filteredRelations.stream() - .allMatch( - rel -> addRequirement(componentInstance, originComponent, component.getComponentInstances(), rel, - toscaRequirements, componentCache)); - } - - private boolean addRequirement(ComponentInstance fromInstance, Component fromOriginComponent, - List instancesList, RequirementCapabilityRelDef rel, - List> toscaRequirements, - Map componentCache) { - - boolean result = true; - Map> reqMap = fromOriginComponent.getRequirements(); - RelationshipInfo reqAndRelationshipPair = rel.getRelationships().get(0).getRelation(); - Either getOriginRes = null; - Optional reqOpt = Optional.empty(); - Component toOriginComponent = null; - Optional capOpt = Optional.empty(); - - ComponentInstance toInstance = instancesList.stream().filter(i -> rel.getToNode().equals(i.getUniqueId())) + } + + private Map buildRequirement(final ComponentInstance fromInstance, + final Component fromOriginComponent, + final List instancesList, + final RequirementCapabilityRelDef relationshipDefinition, + final Map componentCache) + throws ToscaExportException { + + final Map> reqMap = fromOriginComponent.getRequirements(); + final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition + .getRelationships().get(0); + final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation(); + + final ComponentInstance toInstance = instancesList.stream() + .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId())) .findFirst().orElse(null); if (toInstance == null) { - log.debug("Failed to find a relation from the node {} to the node {}", fromInstance.getName(), - rel.getToNode()); - result = false; - } - if (result) { - reqOpt = findRequirement(fromOriginComponent, reqMap, reqAndRelationshipPair, fromInstance.getUniqueId()); - if (!reqOpt.isPresent()) { - log.debug("Failed to find a requirement with uniqueId {} on a component with uniqueId {}", - reqAndRelationshipPair.getRequirementUid(), fromOriginComponent.getUniqueId()); - result = false; + final String errorMsg = String + .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(), + relationshipDefinition.getToNode()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final Optional reqOpt = + findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId()); + if (reqOpt.isEmpty()) { + final String errorMsg = String + .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s", + relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + filter.setIgnoreCapabilities(false); + filter.setIgnoreGroups(false); + final Either getOriginRes = + toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter); + if (getOriginRes.isRight()) { + final String errorMsg = String.format( + "Failed to build substituted name for the requirement %s. " + + "Failed to get an origin component with uniqueId %s", + reqOpt.get().getName(), toInstance.getActualComponentUid()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final Component toOriginComponent = getOriginRes.left().value(); + Optional capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream() + .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst(); + if (capOpt.isEmpty()) { + capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get()); + if (capOpt.isEmpty()) { + final String errorMsg = String + .format("Failed to find a capability with name %s on a component with uniqueId %s", + relationshipInfo.getCapability(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); } } - if (result) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreComponentInstances(false); - filter.setIgnoreCapabilities(false); - filter.setIgnoreGroups(false); - getOriginRes = toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter); - if (getOriginRes.isRight()) { - log.debug( - "Failed to build substituted name for the requirement {}. Failed to get an origin component with uniqueId {}", - reqOpt.get().getName(), toInstance.getActualComponentUid()); - result = false; - } - } - if (result) { - toOriginComponent = getOriginRes.left().value(); - capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream() - .filter(c -> isCapabilityBelongToRelation(reqAndRelationshipPair, c)).findFirst(); - if (!capOpt.isPresent()) { - capOpt = findCapability(reqAndRelationshipPair, toOriginComponent, fromOriginComponent, reqOpt.get()); - if (!capOpt.isPresent()) { - result = false; - log.debug("Failed to find a capability with name {} on a component with uniqueId {}", - reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId()); - } - } - } - if (result) { - result = buildAndAddRequirement(toscaRequirements, fromOriginComponent, toOriginComponent, capOpt.get(), - reqOpt.get(), reqAndRelationshipPair, toInstance, componentCache); - } - return result; + return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(), + capabilityRequirementRelationship, toInstance, componentCache); } private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair, @@ -1383,40 +1395,50 @@ public class ToscaExportHandler { return cap; } - private boolean buildAndAddRequirement(List> toscaRequirements, - Component fromOriginComponent, Component toOriginComponent, - CapabilityDefinition capability, RequirementDefinition requirement, - RelationshipInfo reqAndRelationshipPair, ComponentInstance toInstance, - Map componentCache) { + private Map buildRequirement(final Component fromOriginComponent, + final Component toOriginComponent, + final CapabilityDefinition capability, + final RequirementDefinition requirement, + final CapabilityRequirementRelationship capabilityRequirementRelationship, + final ComponentInstance toInstance, + final Map componentCache) + throws ToscaExportException { + List reducedPath = capability.getPath(); if (capability.getOwnerId() != null) { reducedPath = capabilityRequirementConverter .getReducedPathByOwner(capability.getPath(), capability.getOwnerId()); } - Either buildCapNameRes = capabilityRequirementConverter.buildSubstitutedName(componentCache, - toOriginComponent, reducedPath, reqAndRelationshipPair.getCapability(), capability.getPreviousName()); - if (buildCapNameRes.isRight()) { + final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation(); + final Either capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache, + toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName()); + if (capabilityNameEither.isRight()) { + final String errorMsg = String.format( + "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s", + capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId()); log.debug( - "Failed to build a substituted capability name for the capability with name {} on a component with uniqueId {}", - reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId()); - return false; + errorMsg); + throw new ToscaExportException(errorMsg); } - Either buildReqNameRes = capabilityRequirementConverter + final Either requirementNameEither = capabilityRequirementConverter .buildSubstitutedName(componentCache, fromOriginComponent, - requirement.getPath(), reqAndRelationshipPair.getRequirement(), requirement.getPreviousName()); - if (buildReqNameRes.isRight()) { - log.debug( - "Failed to build a substituted requirement name for the requirement with name {} on a component with uniqueId {}", - reqAndRelationshipPair.getRequirement(), fromOriginComponent.getUniqueId()); - return false; - } - ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); - Map toscaReqMap = new HashMap<>(); + requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName()); + if (requirementNameEither.isRight()) { + final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement " + + "with name %s on a component with uniqueId %s", + capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); + final Map toscaReqMap = new HashMap<>(); toscaRequirement.setNode(toInstance.getName()); - toscaRequirement.setCapability(buildCapNameRes.left().value()); - toscaReqMap.put(buildReqNameRes.left().value(), toscaRequirement); - toscaRequirements.add(toscaReqMap); - return true; + toscaRequirement.setCapability(capabilityNameEither.left().value()); + if (isNotEmpty(capabilityRequirementRelationship.getOperations())) { + toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship)); + } + toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement); + return toscaReqMap; } private Optional findRequirement(Component fromOriginComponent, @@ -1673,12 +1695,83 @@ public class ToscaExportHandler { CustomRepresenter() { super(); + this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment()); // null representer is exceptional and it is stored as an instance // variable. this.nullRepresenter = new RepresentNull(); } + private class RepresentToscaPropertyAssignment implements Represent { + public Node representData(Object data) { + final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data; + if (toscaOperationAssignment.getValue() instanceof String) { + final String stringValue = (String) toscaOperationAssignment.getValue(); + if (isPropertyOrAttributeFunction(stringValue)) { + return representGetAttribute(stringValue); + } + + return representScalar(Tag.STR, stringValue); + } + return represent(null); + } + + public Node representGetAttribute(final String getAttributeFunction) { + return represent(new Yaml().load(getAttributeFunction)); + } + + public boolean isPropertyOrAttributeFunction(final String value) { + try { + final Yaml yaml = new Yaml(); + final Object yamlObj = yaml.load(value); + if (!(yamlObj instanceof Map)) { + return false; + } + final Map getAttributeMap = (Map) yamlObj; + if (getAttributeMap.size() != 1) { + return false; + } + final List functionList = Arrays + .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), + GET_PROPERTY.getFunctionName()); + final Optional function = getAttributeMap.keySet().stream() + .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst(); + + if (function.isEmpty()) { + return false; + } + final String functionName = function.get(); + final Object getAttributeValueObj = getAttributeMap.get(functionName); + if (GET_INPUT.getFunctionName().equals(functionName)) { + return validateGetInputValue(getAttributeValueObj); + } else { + return validateGetPropertyOrAttributeValue(getAttributeValueObj); + } + } catch (final Exception ignored) { + return false; + } + } + } + + public boolean validateGetInputValue(final Object valueObj) { + if (!(valueObj instanceof List) && !(valueObj instanceof String)) { + return false; + } + if (valueObj instanceof List) { + return ((List) valueObj).size() > 1; + } + + return true; + } + + public boolean validateGetPropertyOrAttributeValue(final Object valueObj) { + if (valueObj instanceof List) { + return ((List) valueObj).size() > 1; + } + + return false; + } + @Override protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { @@ -1689,9 +1782,17 @@ public class ToscaExportHandler { if ("dependencies".equals(property.getName())) { return null; } + if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) { + return null; + } + removeDefaultP(propertyValue); NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); + if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) { + return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode()); + } + return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportRelationshipTemplatesHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportRelationshipTemplatesHandler.java new file mode 100644 index 0000000000..c706063d75 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportRelationshipTemplatesHandler.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca; + +import static org.apache.commons.collections.CollectionUtils.isEmpty; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate; +import org.openecomp.sdc.be.tosca.model.ToscaRelationship; +import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate; +import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement; + +/** + * Handles the relationship_templates in the TOSCA export + */ +public class ToscaExportRelationshipTemplatesHandler { + + /** + * Creates the relationship_templates map based on the node_templates requirements. + * + * @param nodeTemplateMap the node template map + * @return the relationship_templates map + */ + public Map createFrom(final Map nodeTemplateMap) { + if (MapUtils.isEmpty(nodeTemplateMap)) { + return Collections.emptyMap(); + } + + final Map relationshipTemplates = new HashMap<>(); + for (final Entry nodeEntry : nodeTemplateMap.entrySet()) { + final ToscaNodeTemplate nodeTemplate = nodeEntry.getValue(); + if (isEmpty(nodeTemplate.getRequirements())) { + continue; + } + final AtomicInteger relationshipTemplateCount = new AtomicInteger(1); + for (final Map requirementMap : nodeTemplate.getRequirements()) { + requirementMap.entrySet().stream() + .filter(entry -> entry.getValue().isRelationshipComplexNotation()) + .forEach(requirementEntry -> { + final ToscaTemplateRequirement requirement = requirementEntry.getValue(); + final ToscaRelationship relationship = requirement.getRelationshipAsComplexType(); + final ToscaRelationshipTemplate relationshipTemplate = new ToscaRelationshipTemplate(); + relationshipTemplate.setType(relationship.getType()); + relationshipTemplate.setInterfaces(relationship.getInterfaces()); + final String relationshipName = String.format("%s.%s", + ToscaRelationshipTemplate + .createRelationshipName(nodeEntry.getKey(), requirementEntry.getKey()), + relationshipTemplateCount); + + requirement.setRelationship(relationshipName); + relationshipTemplate.setName(relationshipName); + relationshipTemplates.put(relationshipName, relationshipTemplate); + relationshipTemplateCount.incrementAndGet(); + }); + } + } + + return relationshipTemplates; + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java new file mode 100644 index 0000000000..c3c9607664 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java @@ -0,0 +1,71 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.builder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; +import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition; +import org.openecomp.sdc.be.tosca.model.ToscaOperationAssignment; +import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment; +import org.openecomp.sdc.be.tosca.model.ToscaRelationship; +import org.openecomp.sdc.be.tosca.utils.InterfaceTypesNameUtil; +import org.openecomp.sdc.be.ui.model.OperationUi; + +public class ToscaRelationshipBuilder { + + public ToscaRelationship from(final CapabilityRequirementRelationship capabilityRequirementRelationship) { + final ToscaRelationship toscaRelationship = new ToscaRelationship(); + final List operations = capabilityRequirementRelationship.getOperations(); + toscaRelationship.setType(capabilityRequirementRelationship.getRelation().getRelationship().getType()); + final Map> operationsByInterfaceType = operations.stream() + .collect(Collectors.groupingBy(OperationUi::getInterfaceType)); + final Map interfaceMap = new HashMap<>(); + for (final Entry> interfaceTypeEntry : operationsByInterfaceType.entrySet()) { + final ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition(); + final String interfaceType = interfaceTypeEntry.getKey(); + final Map operationDefinitionMap = new HashMap<>(); + for (final OperationUi operationUi : interfaceTypeEntry.getValue()) { + final ToscaOperationAssignment toscaOperationAssignment = new ToscaOperationAssignment(); + toscaOperationAssignment.setImplementation(operationUi.getImplementation()); + if (CollectionUtils.isNotEmpty(operationUi.getInputs())) { + final Map inputMap = new HashMap<>(); + operationUi.getInputs().forEach(propertyAssignmentUi -> { + final ToscaPropertyAssignment toscaProperty = new ToscaPropertyAssignment(); + toscaProperty.setValue(propertyAssignmentUi.getValue()); + inputMap.put(propertyAssignmentUi.getName(), toscaProperty); + }); + + toscaOperationAssignment.setInputs(inputMap); + } + operationDefinitionMap.put(operationUi.getOperationType(), toscaOperationAssignment); + } + toscaInterfaceDefinition.setOperations(operationDefinitionMap); + interfaceMap.put(InterfaceTypesNameUtil.buildShortName(interfaceType), toscaInterfaceDefinition); + } + toscaRelationship.setInterfaces(interfaceMap); + return toscaRelationship; + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaOperationAssignment.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaOperationAssignment.java new file mode 100644 index 0000000000..2aba85027e --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaOperationAssignment.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.model; + +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ToscaOperationAssignment { + + private String description; + private String implementation; + private Map inputs; + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignment.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignment.java new file mode 100644 index 0000000000..f42b655cbf --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyAssignment.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.model; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ToscaPropertyAssignment { + + private Object value; + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationship.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationship.java new file mode 100644 index 0000000000..49286ca0e2 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationship.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.model; + +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents a relationship entry in a requirement fulfilment. + */ +@Getter +@Setter +public class ToscaRelationship { + + private String type; + private Map interfaces; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationshipTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationshipTemplate.java new file mode 100644 index 0000000000..f42effab6b --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRelationshipTemplate.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.model; + +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents a relationship_template in the topology_template. + */ +@Getter +@Setter +public class ToscaRelationshipTemplate { + + private String name; + private String type; + private Map interfaces; + + public static String createRelationshipName(final String nodeName, final String requirementName) { + return String.format("%s.%s", nodeName, requirementName); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRequirement.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRequirement.java index 35d5c4e6e1..c8e0527191 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRequirement.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaRequirement.java @@ -21,25 +21,13 @@ package org.openecomp.sdc.be.tosca.model; import java.util.List; -import java.util.Map; +import lombok.Getter; +import lombok.Setter; +@Getter +@Setter public class ToscaRequirement extends ToscaTemplateRequirement { private List occurrences; - public ToscaRequirement() { - } - - public List getOccurrences() { - return occurrences; - } - - public void setOccurrences(List occurrences) { - this.occurrences = occurrences; - } - - public Map toMap() throws IllegalArgumentException, IllegalAccessException { - return super.toMap(); - } - } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateRequirement.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateRequirement.java index 7a77c4f47c..85d01e1469 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateRequirement.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateRequirement.java @@ -20,49 +20,51 @@ package org.openecomp.sdc.be.tosca.model; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; +import lombok.Getter; +import lombok.Setter; +import org.openecomp.sdc.exception.InvalidArgumentException; +@Getter +@Setter public class ToscaTemplateRequirement { private String capability; private String node; - private String relationship; + private Object relationship; - public ToscaTemplateRequirement() { - } - - public String getCapability() { - return capability; - } - - public void setCapability(String capability) { - this.capability = capability; - } - - public String getNode() { - return node; - } - - public void setNode(String node) { - this.node = node; - } - - public String getRelationship() { - return relationship; + public ToscaRelationship getRelationshipAsComplexType() { + if (relationship == null) { + return null; + } + if (relationship instanceof ToscaRelationship) { + return (ToscaRelationship) relationship; + } + final ToscaRelationship toscaRelationship = new ToscaRelationship(); + toscaRelationship.setType((String) relationship); + return toscaRelationship; } - public void setRelationship(String relationship) { + public void setRelationship(final Object relationship) { + if (relationship == null) { + this.relationship = null; + return; + } + if (!(relationship instanceof ToscaRelationship) && !(relationship instanceof String)) { + throw new InvalidArgumentException(String.format("relationship %s type not expected. " + + "Supported types are %s and %s", relationship.getClass(), ToscaRelationship.class, String.class)); + } this.relationship = relationship; } - public Map toMap() throws IllegalArgumentException, IllegalAccessException { - Map map = new HashMap<>(); - Field[] fields = this.getClass().getDeclaredFields(); - for (Field field : fields) { - field.setAccessible(true); - map.put(field.getName(), field.get(this)); - } - return map; + /** + * Checks if the relationship entry is a complex type ({@link ToscaRelationship}). + * + * The relationship can be a simple notation (string) (see Tosca 1.3, Section 3.7.3.2.2), or a multi-line grammar + * notation (complex) (see Tosca 1.3, Section 3.7.3.2.3). + * + * @return {@code true} if the relationship is a complex type, {@code false} otherwise + */ + public boolean isRelationshipComplexNotation() { + return relationship instanceof ToscaRelationship; } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTopolgyTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTopolgyTemplate.java index 0d62521e59..00ab08b677 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTopolgyTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTopolgyTemplate.java @@ -22,25 +22,22 @@ package org.openecomp.sdc.be.tosca.model; import java.util.HashMap; import java.util.Map; +import lombok.Getter; +import lombok.Setter; +@Getter public class ToscaTopolgyTemplate { + + @Setter private Map inputs; + @Setter private Map node_templates; private Map groups; private Map policies; + @Setter private SubstitutionMapping substitution_mappings; - - public Map getNode_templates() { - return node_templates; - } - - public void setNode_templates(Map node_templates) { - this.node_templates = node_templates; - } - - public Map getGroups() { - return groups; - } + @Setter + private Map relationshipTemplates; public void addGroups(Map groups) { if ( this.groups == null ){ @@ -49,30 +46,10 @@ public class ToscaTopolgyTemplate { this.groups.putAll(groups); } - public SubstitutionMapping getSubstitution_mappings() { - return substitution_mappings; - } - - public void setSubstitution_mappings(SubstitutionMapping substitution_mapping) { - this.substitution_mappings = substitution_mapping; - } - - public Map getInputs() { - return inputs; - } - - public void setInputs(Map inputs) { - this.inputs = inputs; - } - public void addPolicies(Map policiesMap) { if ( this.policies == null ){ this.policies = new HashMap<>(); } this.policies.putAll(policiesMap); } - - public Map getPolicies() { - return policies; - } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfaceTypesNameUtil.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfaceTypesNameUtil.java new file mode 100644 index 0000000000..eda8cef250 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfaceTypesNameUtil.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.tosca.utils; + +public class InterfaceTypesNameUtil { + + private InterfaceTypesNameUtil() { + + } + + /** + * Build the short name of an interface_type by grabbing the final name in its path. E.g. + * "tosca.interfaces.relationship.Configure" will be shortened to "Configure". + * + * @param interfaceName the full interface name + * @return the shortened name of the interface + */ + public static String buildShortName(final String interfaceName) { + if (interfaceName == null) { + throw new IllegalArgumentException("interfaceName cannot be null"); + } + final int index = interfaceName.lastIndexOf('.'); + return index > 0 && interfaceName.length() > index + 1 ? interfaceName.substring(index + 1) : interfaceName; + } + +} -- cgit 1.2.3-korg