/*- * ============LICENSE_START======================================================= * SDC * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. * ============LICENSE_END========================================================= * Modifications copyright (c) 2019 Nokia * ================================================================================ */ package org.openecomp.sdc.be.components.csar; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import fj.data.Either; import java.util.Collections; import java.util.EnumMap; import java.util.Objects; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.components.impl.AnnotationBusinessLogic; import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.ImportUtils; import org.openecomp.sdc.be.components.impl.NodeFilterUploadCreator; import org.openecomp.sdc.be.components.impl.PolicyTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao; import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupTypeDefinition; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.PolicyTypeDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.UploadArtifactInfo; import org.openecomp.sdc.be.model.UploadCapInfo; import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; import org.openecomp.sdc.be.model.UploadPropInfo; import org.openecomp.sdc.be.model.UploadReqInfo; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.parser.ParserException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; import static org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import static org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaListElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMapElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.loadYamlAsStrictMap; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ARTIFACTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITY; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.FILE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GET_INPUT; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GROUPS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IS_PASSWORD; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.MEMBERS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.POLICIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIREMENTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TARGETS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES; /** * A handler class designed to parse the YAML file of the service template for a JAVA object */ @Component public class YamlTemplateParsingHandler { private static final Pattern propertyValuePattern = Pattern.compile("[ ]*\\{[ ]*(str_replace=|token=|get_property=|concat=|get_attribute=)+"); private static final int SUB_MAPPING_CAPABILITY_OWNER_NAME_IDX = 0; private static final int SUB_MAPPING_CAPABILITY_NAME_IDX = 1; private static final Logger log = Logger.getLogger(YamlTemplateParsingHandler.class); private Gson gson = new Gson(); private JanusGraphDao janusGraphDao; private GroupTypeBusinessLogic groupTypeBusinessLogic; private AnnotationBusinessLogic annotationBusinessLogic; private PolicyTypeBusinessLogic policyTypeBusinessLogic; public YamlTemplateParsingHandler(JanusGraphDao janusGraphDao, GroupTypeBusinessLogic groupTypeBusinessLogic, AnnotationBusinessLogic annotationBusinessLogic, PolicyTypeBusinessLogic policyTypeBusinessLogic) { this.janusGraphDao = janusGraphDao; this.groupTypeBusinessLogic = groupTypeBusinessLogic; this.annotationBusinessLogic = annotationBusinessLogic; this.policyTypeBusinessLogic = policyTypeBusinessLogic; } public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map createdNodesToscaResourceNames, Map nodeTypesInfo, String nodeName, org.openecomp.sdc.be.model.Component component) { log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName); Map mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName); ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo(); findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL) .left() .on(err -> failIfNotTopologyTemplate(fileName)); parsedToscaYamlInfo.setInputs(getInputs(mappedToscaTemplate)); parsedToscaYamlInfo.setInstances(getInstances(fileName, mappedToscaTemplate, createdNodesToscaResourceNames)); parsedToscaYamlInfo.setGroups(getGroups(fileName, mappedToscaTemplate)); if(component instanceof Resource){ parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate)); } log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName); return parsedToscaYamlInfo; } private Map getMappedToscaTemplate(String fileName, String resourceYml, Map nodeTypesInfo, String nodeName) { Map mappedToscaTemplate; if (isNodeExist(nodeTypesInfo, nodeName)) { mappedToscaTemplate = nodeTypesInfo.get(nodeName).getMappedToscaTemplate(); } else { mappedToscaTemplate = loadYaml(fileName, resourceYml); } return mappedToscaTemplate; } private Map loadYaml(String fileName, String resourceYml) { Map mappedToscaTemplate = null; try { mappedToscaTemplate = loadYamlAsStrictMap(resourceYml); } catch (ParserException e) { log.debug("#getMappedToscaTemplate - Failed to load YAML file {}", fileName, e); rollbackWithException(ActionStatus.TOSCA_PARSE_ERROR, fileName, e.getMessage()); } return mappedToscaTemplate; } private boolean isNodeExist(Map nodeTypesInfo, String nodeName) { return nodeTypesInfo != null && nodeName != null && nodeTypesInfo.containsKey(nodeName); } private Map getInputs(Map toscaJson) { Map inputs = ImportUtils.getInputs(toscaJson, annotationBusinessLogic.getAnnotationTypeOperations()) .left() .on(err -> new HashMap<>()); annotationBusinessLogic.validateAndMergeAnnotationsAndAssignToInput(inputs); return inputs; } private Map getPolicies(String fileName, Map toscaJson) { Map foundPolicies = findFirstToscaMapElement(toscaJson, POLICIES) .left() .on(err -> logPoliciesNotFound(fileName)); if (MapUtils.isNotEmpty(foundPolicies)) { return foundPolicies .entrySet() .stream() .map(this::createPolicy) .collect(Collectors.toMap(PolicyDefinition::getName, p -> p)); } return Collections.emptyMap(); } private PolicyDefinition createPolicy(Map.Entry policyNameValue) { PolicyDefinition emptyPolicyDef = new PolicyDefinition(); String policyName = policyNameValue.getKey(); emptyPolicyDef.setName(policyName); try { if (policyNameValue.getValue() != null && policyNameValue.getValue() instanceof Map) { Map policyTemplateJsonMap = (Map) policyNameValue.getValue(); validateAndFillPolicy(emptyPolicyDef, policyTemplateJsonMap); } else { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } } catch (ClassCastException e) { log.debug("#createPolicy - Failed to create the policy {}. The exception occurred", policyName, e); rollbackWithException(ActionStatus.INVALID_YAML); } return emptyPolicyDef; } private Map logPoliciesNotFound(String fileName) { log.debug("#logPoliciesNotFound - Policies were not found in the yaml template {}.", fileName); return Collections.emptyMap(); } private void validateAndFillPolicy(PolicyDefinition emptyPolicyDefinition, Map policyTemplateJsonMap) { String policyTypeName = (String) policyTemplateJsonMap.get(TYPE.getElementName()); if(StringUtils.isEmpty(policyTypeName)){ log.debug("#validateAndFillPolicy - The 'type' member is not found under policy {}", emptyPolicyDefinition.getName()); rollbackWithException(ActionStatus.POLICY_MISSING_POLICY_TYPE, emptyPolicyDefinition.getName()); } emptyPolicyDefinition.setType(policyTypeName); // set policy targets emptyPolicyDefinition.setTargets(validateFillPolicyTargets(policyTemplateJsonMap)); PolicyTypeDefinition policyTypeDefinition = validateGetPolicyTypeDefinition(policyTypeName); // set policy properties emptyPolicyDefinition.setProperties(validateFillPolicyProperties(policyTypeDefinition, policyTemplateJsonMap)); } private PolicyTypeDefinition validateGetPolicyTypeDefinition(String policyType) { PolicyTypeDefinition policyTypeDefinition = policyTypeBusinessLogic.getLatestPolicyTypeByType(policyType); if (policyTypeDefinition == null) { log.debug("#validateAndFillPolicy - The policy type {} not found", policyType); rollbackWithException(ActionStatus.POLICY_TYPE_IS_INVALID, policyType); } return policyTypeDefinition; } private List validateFillPolicyProperties(PolicyTypeDefinition policyTypeDefinition, Map policyTemplateJsonMap) { if (MapUtils.isEmpty(policyTemplateJsonMap) || Objects.isNull(policyTypeDefinition)) { return Collections.emptyList(); } List propertyDataDefinitionList = new ArrayList<>(); Map propertiesMap = (Map) policyTemplateJsonMap.get(PROPERTIES.getElementName()); if (MapUtils.isEmpty(propertiesMap)) { return Collections.emptyList(); } if (CollectionUtils.isNotEmpty(policyTypeDefinition.getProperties())) { propertyDataDefinitionList = policyTypeDefinition .getProperties() .stream() .map(propertyDefinition -> setPropertyValue(propertiesMap, propertyDefinition)) .collect(Collectors.toList()); } return propertyDataDefinitionList; } private PropertyDataDefinition setPropertyValue(Map propertiesMap, PropertyDataDefinition srcPropertyDataDefinition) { PropertyDataDefinition newPropertyDef = new PropertyDataDefinition(srcPropertyDataDefinition); String propertyName = newPropertyDef.getName(); if (Objects.nonNull(propertiesMap.get(propertyName))) { Object propValue = propertiesMap.get(propertyName); newPropertyDef.setValue(PropertiesUtils.trimQuotes(gson.toJson(propValue))); } return newPropertyDef; } private Map> validateFillPolicyTargets(Map policyTemplateJson) { Map> targets = new EnumMap<>(PolicyTargetType.class); if (policyTemplateJson.containsKey(TARGETS.getElementName()) && policyTemplateJson.get(TARGETS.getElementName()) instanceof List ) { List targetsElement = (List) policyTemplateJson.get(TARGETS.getElementName()); targets.put(PolicyTargetType.COMPONENT_INSTANCES, targetsElement); } return targets; } private Map getInstances(String yamlName, Map toscaJson, Map createdNodesToscaResourceNames) { Map nodeTemlates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES) .left() .on(err -> failIfNoNodeTemplates(yamlName)); return getInstances(toscaJson, createdNodesToscaResourceNames, nodeTemlates); } private Map getInstances(Map toscaJson, Map createdNodesToscaResourceNames, Map nodeTemlates) { Map moduleComponentInstances; Map substitutionMappings = getSubstitutionMappings(toscaJson); moduleComponentInstances = nodeTemlates.entrySet() .stream() .map(node -> buildModuleComponentInstanceInfo(node, substitutionMappings, createdNodesToscaResourceNames)) .collect(Collectors.toMap(UploadComponentInstanceInfo::getName, i -> i)); return moduleComponentInstances; } private Map getSubstitutionMappings(Map toscaJson) { Map substitutionMappings = null; Either, ResultStatusEnum> eitherSubstitutionMappings = findFirstToscaMapElement(toscaJson, SUBSTITUTION_MAPPINGS); if (eitherSubstitutionMappings.isLeft()) { substitutionMappings = eitherSubstitutionMappings.left().value(); } return substitutionMappings; } @SuppressWarnings("unchecked") private Map getGroups(String fileName, Map toscaJson) { Map foundGroups = findFirstToscaMapElement(toscaJson, GROUPS) .left() .on(err -> logGroupsNotFound(fileName)); if (MapUtils.isNotEmpty(foundGroups)) { Map groups = foundGroups .entrySet() .stream() .map(this::createGroup) .collect(Collectors.toMap(GroupDefinition::getName, g -> g)); Map substitutionMappings = getSubstitutionMappings(toscaJson); if (capabilitiesSubstitutionMappingsExist(substitutionMappings)) { groups.entrySet().forEach(entry -> updateCapabilitiesNames(entry.getValue(), getNamesToUpdate(entry.getKey(), (Map>) substitutionMappings.get(CAPABILITIES.getElementName())))); } return groups; } return new HashMap<>(); } private Map logGroupsNotFound(String fileName) { log.debug("#logGroupsNotFound - Groups were not found in the yaml template {}.", fileName); return new HashMap<>(); } private void updateCapabilitiesNames(GroupDefinition group, Map capabilityNames) { if (MapUtils.isNotEmpty(group.getCapabilities())) { group.getCapabilities().values() .stream() .flatMap(Collection::stream) .filter(cap -> capabilityNames.containsKey(cap.getName())) .forEach(cap -> cap.setName(capabilityNames.get(cap.getName()))); } } private Map getNamesToUpdate(String name, Map> pair) { return pair.entrySet().stream() .filter(e -> e.getValue().get(SUB_MAPPING_CAPABILITY_OWNER_NAME_IDX).equalsIgnoreCase(name)) .collect(Collectors.toMap(e -> e.getValue().get(SUB_MAPPING_CAPABILITY_NAME_IDX), Map.Entry::getKey, (n1 ,n2) -> n1)); } private boolean capabilitiesSubstitutionMappingsExist(Map substitutionMappings) { return substitutionMappings != null && substitutionMappings.containsKey(CAPABILITIES.getElementName()); } private GroupDefinition createGroup(Map.Entry groupNameValue) { GroupDefinition group = new GroupDefinition(); group.setName(groupNameValue.getKey()); try { if (groupNameValue.getValue() != null && groupNameValue.getValue() instanceof Map) { Map groupTemplateJsonMap = (Map) groupNameValue.getValue(); validateAndFillGroup(group, groupTemplateJsonMap); validateUpdateGroupProperties(group, groupTemplateJsonMap); validateUpdateGroupCapabilities(group, groupTemplateJsonMap); } else { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } } catch (ClassCastException e) { log.debug("#createGroup - Failed to create the group {}. The exception occure", groupNameValue.getKey(), e); rollbackWithException(ActionStatus.INVALID_YAML); } return group; } private Map addCapabilities(Map cap, Map otherCap) { cap.putAll(otherCap); return cap; } private Map addCapability(CapabilityDefinition cap) { Map map = Maps.newHashMap(); map.put(cap.getName(), cap); return map; } private void setMembers(GroupDefinition groupInfo, Map groupTemplateJsonMap) { if (groupTemplateJsonMap.containsKey(MEMBERS.getElementName())) { Object members = groupTemplateJsonMap.get(MEMBERS.getElementName()); if (members != null) { if (members instanceof List) { setMembersFromList(groupInfo, (List) members); } else { log.debug("The 'members' member is not of type list under group {}", groupInfo.getName()); rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } } } } private void setMembersFromList(GroupDefinition groupInfo, List membersAsList) { groupInfo.setMembers(membersAsList .stream() .collect(Collectors.toMap(Object::toString, member -> ""))); } @SuppressWarnings("unchecked") private void validateUpdateGroupProperties(GroupDefinition groupInfo, Map groupTemplateJsonMap) { if (groupTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { Object propertiesElement = groupTemplateJsonMap.get(PROPERTIES.getElementName()); if (propertiesElement instanceof Map){ mergeGroupProperties(groupInfo, (Map) propertiesElement); } } } private void mergeGroupProperties(GroupDefinition groupInfo, Map parsedProperties) { if(CollectionUtils.isNotEmpty(groupInfo.getProperties())){ validateGroupProperties(parsedProperties, groupInfo); groupInfo.getProperties().forEach(p -> mergeGroupProperty(p, parsedProperties)); } } private void mergeGroupProperty(PropertyDataDefinition property, Map parsedProperties) { if(parsedProperties.containsKey(property.getName())){ Object propValue = parsedProperties.get(property.getName()); if (valueNotContainsPattern(propertyValuePattern, propValue)) { setPropertyValueAndGetInputsValues(property, propValue); } } } private void setPropertyValueAndGetInputsValues(PropertyDataDefinition property, Object propValue) { if(propValue != null){ UploadPropInfo uploadPropInfo = buildProperty(property.getName(), propValue); property.setValue(convertPropertyValue(ToscaPropertyType.isValidType(property.getType()), uploadPropInfo.getValue())); property.setGetInputValues(uploadPropInfo.getGet_input()); } } private String convertPropertyValue(ToscaPropertyType type, Object value) { String convertedValue = null; if (value != null) { if (type == null || value instanceof Map || value instanceof List) { convertedValue = gson.toJson(value); } else { convertedValue = value.toString(); } } return convertedValue; } private void setDescription(GroupDefinition groupInfo, Map groupTemplateJsonMap) { if (groupTemplateJsonMap.containsKey(DESCRIPTION.getElementName())) { groupInfo.setDescription( (String) groupTemplateJsonMap.get(DESCRIPTION.getElementName())); } } private void validateAndFillGroup(GroupDefinition groupInfo, Map groupTemplateJsonMap) { String type = (String) groupTemplateJsonMap.get(TYPE.getElementName()); if(StringUtils.isEmpty(type)){ log.debug("#validateAndFillGroup - The 'type' member is not found under group {}", groupInfo.getName()); rollbackWithException(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupInfo.getName()); } groupInfo.setType(type); GroupTypeDefinition groupType = groupTypeBusinessLogic.getLatestGroupTypeByType(type); if (groupType == null) { log.debug("#validateAndFillGroup - The group type {} not found", groupInfo.getName()); rollbackWithException(ActionStatus.GROUP_TYPE_IS_INVALID, type); } groupInfo.convertFromGroupProperties(groupType.getProperties()); groupInfo.convertCapabilityDefinitions(groupType.getCapabilities()); setDescription(groupInfo, groupTemplateJsonMap); setMembers(groupInfo, groupTemplateJsonMap); } @SuppressWarnings("unchecked") private void validateUpdateGroupCapabilities(GroupDefinition groupInfo, Map groupTemplateJsonMap) { if (groupTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) { Object capabilities = groupTemplateJsonMap.get(CAPABILITIES.getElementName()); if (capabilities instanceof List) { validateUpdateCapabilities(groupInfo, ((List) capabilities).stream() .map(o -> buildGroupCapability(groupInfo, o)) .collect(Collectors.toMap(CapabilityDefinition::getType, this::addCapability, this::addCapabilities))); } else if (capabilities instanceof Map) { validateUpdateCapabilities(groupInfo, ((Map) capabilities).entrySet() .stream() .map(e -> buildGroupCapability(groupInfo, e)) .collect(Collectors.toMap(CapabilityDefinition::getType, this::addCapability, this::addCapabilities))); } else { log.debug("#setCapabilities - Failed to import the capabilities of the group {}. ", groupInfo.getName()); rollbackWithException(ActionStatus.INVALID_YAML); } } } private void validateUpdateCapabilities(GroupDefinition groupInfo, Map> capabilityInfo) { validateGroupCapabilities(groupInfo, capabilityInfo); groupInfo.updateCapabilitiesProperties(capabilityInfo); } private void validateGroupCapabilities(GroupDefinition group, Map> parsedCapabilities) { if (MapUtils.isNotEmpty(parsedCapabilities)) { if (MapUtils.isEmpty(group.getCapabilities())) { failOnMissingCapabilityTypes(group, Lists.newArrayList(parsedCapabilities.keySet())); } List missingCapTypes = parsedCapabilities.keySet().stream().filter(ct -> !group.getCapabilities().containsKey(ct)).collect(toList()); if (CollectionUtils.isNotEmpty(missingCapTypes)) { failOnMissingCapabilityTypes(group, missingCapTypes); } group.getCapabilities().entrySet().forEach(e -> validateCapabilities(group, e.getValue(), parsedCapabilities.get(e.getKey()))); } } private void validateCapabilities(GroupDefinition group, List capabilities, Map parsedCapabilities) { List allowedCapNames = capabilities.stream().map(CapabilityDefinition::getName).distinct().collect(toList()); List missingCapNames = parsedCapabilities.keySet().stream().filter(c -> !allowedCapNames.contains(c)).collect(toList()); if (CollectionUtils.isNotEmpty(missingCapNames)) { failOnMissingCapabilityNames(group, missingCapNames); } validateCapabilitiesProperties(capabilities, parsedCapabilities); } private void validateCapabilitiesProperties(List capabilities, Map parsedCapabilities) { capabilities.forEach(c -> validateCapabilityProperties(c, parsedCapabilities.get(c.getName()))); } private void validateCapabilityProperties(CapabilityDefinition capability, CapabilityDefinition parsedCapability) { if(parsedCapability != null && parsedCapability.getProperties() != null){ List parsedPropertiesNames = parsedCapability.getProperties() .stream() .map(ComponentInstanceProperty::getName).collect(toList()); validateProperties(capability.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.PROPERTY_NOT_FOUND, capability.getName(), capability.getType()); } } private void validateGroupProperties(Map parsedProperties, GroupDefinition groupInfo) { List parsedPropertiesNames = parsedProperties.entrySet() .stream() .map(Map.Entry::getKey).collect(toList()); validateProperties(groupInfo.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.GROUP_PROPERTY_NOT_FOUND, groupInfo.getName(), groupInfo.getType()); } private void validateProperties(List validProperties, List parsedProperties, ActionStatus actionStatus, String name, String type) { if (CollectionUtils.isNotEmpty(parsedProperties)) { verifyMissingProperties(actionStatus, name, type, parsedProperties .stream() .filter(n -> !validProperties.contains(n)) .collect(toList())); } } private void verifyMissingProperties(ActionStatus actionStatus, String name, String type, List missingProperties) { if (CollectionUtils.isNotEmpty(missingProperties)) { log.debug("#validateProperties - Failed to validate properties. The properties {} are missing on {} of the type {}. ", missingProperties.toString(), name, type); rollbackWithException(actionStatus, missingProperties.toString(), missingProperties.toString(), name, type); } } @SuppressWarnings("unchecked") private CapabilityDefinition buildGroupCapability(GroupDefinition groupInfo, Object capObject) { if (!(capObject instanceof Map)) { log.debug("#convertToGroupCapability - Failed to import the capability {}. ", capObject); rollbackWithException(ActionStatus.INVALID_YAML); } return buildGroupCapability(groupInfo, ((Map) capObject).entrySet().iterator().next()); } @SuppressWarnings("unchecked") private CapabilityDefinition buildGroupCapability(GroupDefinition groupInfo, Map.Entry capEntry) { CapabilityDefinition capability = new CapabilityDefinition(); capability.setOwnerType(CapabilityDataDefinition.OwnerType.GROUP); capability.setName(capEntry.getKey()); capability.setParentName(capEntry.getKey()); capability.setOwnerId(groupInfo.getName()); if (!(capEntry.getValue() instanceof Map)) { log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. ", capEntry.getKey()); rollbackWithException(ActionStatus.INVALID_YAML); } Map capabilityValue = (Map) capEntry.getValue(); String type = (String) capabilityValue.get(TYPE.getElementName()); if (StringUtils.isEmpty(type)) { log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. Missing capability type. ", capEntry.getKey()); rollbackWithException(ActionStatus.INVALID_YAML); } capability.setType(type); if (!(capabilityValue.get(PROPERTIES.getElementName()) instanceof Map)) { log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. ", capEntry.getKey()); rollbackWithException(ActionStatus.INVALID_YAML); } Map properties = (Map) capabilityValue.get(PROPERTIES.getElementName()); capability.setProperties(properties.entrySet().stream().map(this::convertToProperty).collect(toList())); return capability; } private ComponentInstanceProperty convertToProperty(Map.Entry e) { ComponentInstanceProperty property = new ComponentInstanceProperty(); property.setName(e.getKey()); property.setValue((String) e.getValue()); return property; } @SuppressWarnings("unchecked") private UploadComponentInstanceInfo buildModuleComponentInstanceInfo( Map.Entry nodeTemplateJsonEntry, Map substitutionMappings, Map createdNodesToscaResourceNames) { UploadComponentInstanceInfo nodeTemplateInfo = new UploadComponentInstanceInfo(); nodeTemplateInfo.setName(nodeTemplateJsonEntry.getKey()); try { if (nodeTemplateJsonEntry.getValue() instanceof String) { String nodeTemplateJsonString = (String) nodeTemplateJsonEntry.getValue(); nodeTemplateInfo.setType(nodeTemplateJsonString); } else if (nodeTemplateJsonEntry.getValue() instanceof Map) { Map nodeTemplateJsonMap = (Map) nodeTemplateJsonEntry.getValue(); setToscaResourceType(createdNodesToscaResourceNames, nodeTemplateInfo, nodeTemplateJsonMap); setRequirements(nodeTemplateInfo, nodeTemplateJsonMap); setCapabilities(nodeTemplateInfo, nodeTemplateJsonMap); setArtifacts(nodeTemplateInfo, nodeTemplateJsonMap); updateProperties(nodeTemplateInfo, nodeTemplateJsonMap); setDirectives(nodeTemplateInfo, nodeTemplateJsonMap); setNodeFilter(nodeTemplateInfo, nodeTemplateJsonMap); setSubstitutions(substitutionMappings, nodeTemplateInfo); } else { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } } catch (ClassCastException e) { BeEcompErrorManager.getInstance().logBeSystemError("Import Resource - create capability"); log.debug("error when creating capability, message:{}", e.getMessage(), e); rollbackWithException(ActionStatus.INVALID_YAML); } return nodeTemplateInfo; } @SuppressWarnings("unchecked") private void setSubstitutions(Map substitutionMappings, UploadComponentInstanceInfo nodeTemplateInfo) { if (substitutionMappings != null) { if (substitutionMappings.containsKey(CAPABILITIES.getElementName())) { nodeTemplateInfo.setCapabilitiesNamesToUpdate(getNamesToUpdate(nodeTemplateInfo.getName(), (Map>) substitutionMappings .get(CAPABILITIES.getElementName()))); } if (substitutionMappings.containsKey(REQUIREMENTS.getElementName())) { nodeTemplateInfo.setRequirementsNamesToUpdate(getNamesToUpdate( nodeTemplateInfo.getName(), (Map>) substitutionMappings .get(REQUIREMENTS.getElementName()))); } } } private void updateProperties(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { Map> properties = buildPropModuleFromYaml(nodeTemplateJsonMap); if (!properties.isEmpty()) { nodeTemplateInfo.setProperties(properties); } } } private void setCapabilities(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) { Map> eitherCapRes = createCapModuleFromYaml(nodeTemplateJsonMap); if (!eitherCapRes.isEmpty()) { nodeTemplateInfo.setCapabilities(eitherCapRes); } } } private void setArtifacts(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(ARTIFACTS.getElementName())) { Map> eitherArtifactsRes = createArtifactsModuleFromYaml(nodeTemplateJsonMap); if (!eitherArtifactsRes.isEmpty()) { nodeTemplateInfo.setArtifacts(eitherArtifactsRes); } } } private void setRequirements(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(REQUIREMENTS.getElementName())) { Map> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap); if (!regResponse.isEmpty()) { nodeTemplateInfo.setRequirements(regResponse); } } } private void setToscaResourceType(Map createdNodesToscaResourceNames, UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(TYPE.getElementName())) { String toscaResourceType = (String) nodeTemplateJsonMap.get(TYPE.getElementName()); if (createdNodesToscaResourceNames.containsKey(toscaResourceType)) { toscaResourceType = createdNodesToscaResourceNames.get(toscaResourceType); } nodeTemplateInfo.setType(toscaResourceType); } } private void setDirectives(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { List directives = (List) nodeTemplateJsonMap.get(TypeUtils.ToscaTagNamesEnum.DIRECTIVES.getElementName()); nodeTemplateInfo.setDirectives(directives); } private void setNodeFilter(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName())) { nodeTemplateInfo.setUploadNodeFilterInfo( new NodeFilterUploadCreator().createNodeFilterData(nodeTemplateJsonMap.get( TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName()))); } } @SuppressWarnings("unchecked") private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleRequirements = new HashMap<>(); Either, ResultStatusEnum> requirementsListRes = findFirstToscaListElement(nodeTemplateJsonMap, REQUIREMENTS); if (requirementsListRes.isLeft()) { for (Object jsonReqObj : requirementsListRes.left().value()) { String reqName = ((Map) jsonReqObj).keySet().iterator().next(); Object reqJson = ((Map) jsonReqObj).get(reqName); addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); } } else { Either, ResultStatusEnum> requirementsMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, REQUIREMENTS); if (requirementsMapRes.isLeft()) { for (Map.Entry entry : requirementsMapRes.left().value().entrySet()) { String reqName = entry.getKey(); Object reqJson = entry.getValue(); addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); } } } return moduleRequirements; } private void addModuleNodeTemplateReq(Map> moduleRequirements, Object requirementJson, String requirementName) { UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson); requirement.setName(requirementName); if (moduleRequirements.containsKey(requirementName)) { moduleRequirements.get(requirementName).add(requirement); } else { List list = new ArrayList<>(); list.add(requirement); moduleRequirements.put(requirementName, list); } } @SuppressWarnings("unchecked") private Map> createArtifactsModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleArtifacts = new HashMap<>(); Either, ResultStatusEnum> ArtifactsListRes = findFirstToscaListElement(nodeTemplateJsonMap, ARTIFACTS); if (ArtifactsListRes.isLeft()) { for (Object jsonArtifactObj : ArtifactsListRes.left().value()) { String key = ((Map) jsonArtifactObj).keySet().iterator().next(); Object artifactJson = ((Map) jsonArtifactObj).get(key); addModuleNodeTemplateArtifacts(moduleArtifacts, artifactJson, key); } } else { Either>, ResultStatusEnum> ArtifactsMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, ARTIFACTS); if (ArtifactsMapRes.isLeft()) { for (Map.Entry> entry : ArtifactsMapRes.left().value().entrySet()) { String artifactName = entry.getKey(); Object artifactJson = entry.getValue(); addModuleNodeTemplateArtifacts(moduleArtifacts, artifactJson, artifactName); } } } return moduleArtifacts; } private void addModuleNodeTemplateArtifacts(Map> moduleArtifacts, Object artifactJson, String artifactName) { UploadArtifactInfo artifact = buildModuleNodeTemplateArtifact(artifactJson); artifact.setName(artifactName); if (moduleArtifacts.containsKey(ARTIFACTS.getElementName())) { moduleArtifacts.get(ARTIFACTS.getElementName()).put(artifactName, artifact); } else { Map map = new HashMap<>(); map.put(artifactName, artifact); moduleArtifacts.put(ARTIFACTS.getElementName(), map); } } @SuppressWarnings("unchecked") private UploadArtifactInfo buildModuleNodeTemplateArtifact(Object artifactObject) { UploadArtifactInfo artifactTemplateInfo = new UploadArtifactInfo(); if (artifactObject instanceof Map) { fillArtifact(artifactTemplateInfo, (Map) artifactObject); } return artifactTemplateInfo; } private void fillArtifact(UploadArtifactInfo artifactTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(TYPE.getElementName())) { artifactTemplateInfo.setType((String) nodeTemplateJsonMap.get(TYPE.getElementName())); } if (nodeTemplateJsonMap.containsKey(FILE.getElementName())) { artifactTemplateInfo.setFile((String) nodeTemplateJsonMap.get(FILE.getElementName())); } } @SuppressWarnings("unchecked") private Map> createCapModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleCap = new HashMap<>(); Either, ResultStatusEnum> capabilitiesListRes = findFirstToscaListElement(nodeTemplateJsonMap, CAPABILITIES); if (capabilitiesListRes.isLeft()) { for (Object jsonCapObj : capabilitiesListRes.left().value()) { String key = ((Map) jsonCapObj).keySet().iterator().next(); Object capJson = ((Map) jsonCapObj).get(key); addModuleNodeTemplateCap(moduleCap, capJson, key); } } else { Either, ResultStatusEnum> capabilitiesMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, CAPABILITIES); if (capabilitiesMapRes.isLeft()) { for (Map.Entry entry : capabilitiesMapRes.left().value().entrySet()) { String capName = entry.getKey(); Object capJson = entry.getValue(); addModuleNodeTemplateCap(moduleCap, capJson, capName); } } } return moduleCap; } private void addModuleNodeTemplateCap(Map> moduleCap, Object capJson, String key) { UploadCapInfo capabilityDef = buildModuleNodeTemplateCap(capJson); capabilityDef.setKey(key); if (moduleCap.containsKey(key)) { moduleCap.get(key).add(capabilityDef); } else { List list = new ArrayList<>(); list.add(capabilityDef); moduleCap.put(key, list); } } @SuppressWarnings("unchecked") private UploadCapInfo buildModuleNodeTemplateCap(Object capObject) { UploadCapInfo capTemplateInfo = new UploadCapInfo(); if (capObject instanceof String) { String nodeTemplateJsonString = (String) capObject; capTemplateInfo.setNode(nodeTemplateJsonString); } else if (capObject instanceof Map) { fillCapability(capTemplateInfo, (Map) capObject); } return capTemplateInfo; } private void fillCapability(UploadCapInfo capTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(NODE.getElementName())) { capTemplateInfo.setNode((String) nodeTemplateJsonMap.get(NODE.getElementName())); } if (nodeTemplateJsonMap.containsKey(TYPE.getElementName())) { capTemplateInfo.setType((String) nodeTemplateJsonMap.get(TYPE.getElementName())); } if (nodeTemplateJsonMap.containsKey(VALID_SOURCE_TYPES.getElementName())) { Either, ResultStatusEnum> validSourceTypesRes = findFirstToscaListElement(nodeTemplateJsonMap, VALID_SOURCE_TYPES); if (validSourceTypesRes.isLeft()) { capTemplateInfo.setValidSourceTypes(validSourceTypesRes.left().value().stream() .map(Object::toString).collect(toList())); } } if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { Map> props = buildPropModuleFromYaml(nodeTemplateJsonMap); if (!props.isEmpty()) { List properties = props.values().stream().flatMap(Collection::stream).collect(toList()); capTemplateInfo.setProperties(properties); } } } @SuppressWarnings("unchecked") private UploadReqInfo buildModuleNodeTemplateReg(Object regObject) { UploadReqInfo regTemplateInfo = new UploadReqInfo(); if (regObject instanceof String) { String nodeTemplateJsonString = (String) regObject; regTemplateInfo.setNode(nodeTemplateJsonString); } else if (regObject instanceof Map) { Map nodeTemplateJsonMap = (Map) regObject; if (nodeTemplateJsonMap.containsKey(NODE.getElementName())) { regTemplateInfo.setNode((String) nodeTemplateJsonMap.get(NODE.getElementName())); } if (nodeTemplateJsonMap.containsKey(CAPABILITY.getElementName())) { regTemplateInfo.setCapabilityName( (String) nodeTemplateJsonMap.get(CAPABILITY.getElementName())); } } return regTemplateInfo; } private Map> buildPropModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleProp = new HashMap<>(); Either, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(nodeTemplateJsonMap, PROPERTIES); if (toscaProperties.isLeft()) { Map jsonProperties = toscaProperties.left().value(); for (Map.Entry jsonPropObj : jsonProperties.entrySet()) { if (valueNotContainsPattern(propertyValuePattern, jsonPropObj.getValue())) { addProperty(moduleProp, jsonPropObj); } } } return moduleProp; } private void addProperty(Map> moduleProp, Map.Entry jsonPropObj) { UploadPropInfo propertyDef = buildProperty(jsonPropObj.getKey(), jsonPropObj.getValue()); if (moduleProp.containsKey(propertyDef.getName())) { moduleProp.get(propertyDef.getName()).add(propertyDef); } else { List list = new ArrayList<>(); list.add(propertyDef); moduleProp.put(propertyDef.getName(), list); } } @SuppressWarnings("unchecked") private UploadPropInfo buildProperty(String propName, Object propValue) { UploadPropInfo propertyDef = new UploadPropInfo(); propertyDef.setValue(propValue); propertyDef.setName(propName); if (propValue instanceof Map) { if (((Map) propValue).containsKey(TYPE.getElementName())) { propertyDef.setType(((Map) propValue) .get(TYPE.getElementName()).toString()); } if (containsGetInput(propValue)) { fillInputRecursively(propName, (Map) propValue, propertyDef); } if (((Map) propValue).containsKey(DESCRIPTION.getElementName())) { propertyDef.setDescription(((Map) propValue) .get(DESCRIPTION.getElementName()).toString()); } if (((Map) propValue) .containsKey(DEFAULT_VALUE.getElementName())) { propertyDef.setValue(((Map) propValue) .get(DEFAULT_VALUE.getElementName())); } if (((Map) propValue).containsKey(IS_PASSWORD.getElementName())) { propertyDef.setPassword(Boolean.getBoolean(((Map) propValue) .get(IS_PASSWORD.getElementName()).toString())); } else { propertyDef.setValue(propValue); } } else if (propValue instanceof List) { List propValueList = (List) propValue; fillInputsListRecursively(propertyDef, propValueList); propertyDef.setValue(propValue); } return propertyDef; } @SuppressWarnings("unchecked") private boolean containsGetInput(Object propValue) { return ((Map) propValue).containsKey(GET_INPUT.getElementName()) || ImportUtils.containsGetInput(propValue); } @SuppressWarnings("unchecked") private void fillInputsListRecursively(UploadPropInfo propertyDef, List propValueList) { for (Object objValue : propValueList) { if (objValue instanceof Map) { Map objMap = (Map) objValue; if (objMap.containsKey(GET_INPUT.getElementName())) { fillInputRecursively(propertyDef.getName(), objMap, propertyDef); } else { Set keys = objMap.keySet(); findAndFillInputsListRecursively(propertyDef, objMap, keys); } } else if (objValue instanceof List) { List propSubValueList = (List) objValue; fillInputsListRecursively(propertyDef, propSubValueList); } } } @SuppressWarnings("unchecked") private void findAndFillInputsListRecursively(UploadPropInfo propertyDef, Map objMap, Set keys) { for (String key : keys) { Object value = objMap.get(key); if (value instanceof Map) { fillInputRecursively(key, (Map) value, propertyDef); } else if (value instanceof List) { List propSubValueList = (List) value; fillInputsListRecursively(propertyDef, propSubValueList); } } } private void fillInputRecursively(String propName, Map propValue, UploadPropInfo propertyDef) { if (propValue.containsKey(GET_INPUT.getElementName())) { Object getInput = propValue.get(GET_INPUT.getElementName()); GetInputValueDataDefinition getInputInfo = new GetInputValueDataDefinition(); List getInputs = propertyDef.getGet_input(); if (getInputs == null) { getInputs = new ArrayList<>(); } if (getInput instanceof String) { getInputInfo.setInputName((String) getInput); getInputInfo.setPropName(propName); } else if (getInput instanceof List) { fillInput(propName, getInput, getInputInfo); } getInputs.add(getInputInfo); propertyDef.setGet_input(getInputs); propertyDef.setValue(propValue); } else { findAndFillInputRecursively(propValue, propertyDef); } } @SuppressWarnings("unchecked") private void findAndFillInputRecursively(Map propValue, UploadPropInfo propertyDef) { for (String propName : propValue.keySet()) { Object value = propValue.get(propName); if (value instanceof Map) { fillInputRecursively(propName, (Map) value, propertyDef); } else if (value instanceof List) { fillInputsRecursively(propertyDef, propName, (List) value); } } } private void fillInputsRecursively(UploadPropInfo propertyDef, String propName, List inputs) { inputs.stream() .filter(o -> o instanceof Map) .forEach(o -> fillInputRecursively(propName, (Map)o, propertyDef)); } @SuppressWarnings("unchecked") private void fillInput(String propName, Object getInput, GetInputValueDataDefinition getInputInfo) { List getInputList = (List) getInput; getInputInfo.setPropName(propName); getInputInfo.setInputName((String) getInputList.get(0)); if (getInputList.size() > 1) { Object indexObj = getInputList.get(1); if (indexObj instanceof Integer) { getInputInfo.setIndexValue((Integer) indexObj); } else if (indexObj instanceof Float) { int index = ((Float) indexObj).intValue(); getInputInfo.setIndexValue(index); } else if (indexObj instanceof Map && ((Map) indexObj) .containsKey(GET_INPUT.getElementName())) { Object index = ((Map) indexObj) .get(GET_INPUT.getElementName()); GetInputValueDataDefinition getInputInfoIndex = new GetInputValueDataDefinition(); getInputInfoIndex.setInputName((String) index); getInputInfoIndex.setPropName(propName); getInputInfo.setGetInputIndex(getInputInfoIndex); } getInputInfo.setList(true); } } private boolean valueNotContainsPattern(Pattern pattern, Object propValue) { return propValue == null || !pattern.matcher(propValue.toString()).find(); } private Map failIfNoNodeTemplates(String fileName) { janusGraphDao.rollback(); throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName); } private Object failIfNotTopologyTemplate(String fileName) { janusGraphDao.rollback(); throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName); } private void rollbackWithException(ActionStatus actionStatus, String... params) { janusGraphDao.rollback(); throw new ByActionStatusComponentException(actionStatus, params); } private void failOnMissingCapabilityTypes(GroupDefinition groupDefinition, List missingCapTypes) { log.debug("#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ", groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType()); if(CollectionUtils.isNotEmpty(missingCapTypes)) { rollbackWithException(ActionStatus.MISSING_CAPABILITY_TYPE, missingCapTypes.toString()); } } private void failOnMissingCapabilityNames(GroupDefinition groupDefinition, List missingCapNames) { log.debug("#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ", groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType()); rollbackWithException(ActionStatus.MISSING_CAPABILITIES, missingCapNames.toString(), CapabilityDataDefinition.OwnerType.GROUP.getValue(), groupDefinition.getName()); } }