X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fcomponents%2Fimpl%2FResourceImportManager.java;h=1e2cea5c640bb68022fe4e95bbdcd676610e158d;hb=adb7f7496af6e71e1cced44ee2f7485c9917a806;hp=ac6183db0069ee6a4af793dbafdf34d8b8bc6375;hpb=6789ffa5b9dad20c0b60f427f5b6fe432d689d51;p=sdc.git diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java index ac6183db00..1e2cea5c64 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java @@ -7,21 +7,28 @@ * 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.impl; +import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementOperation.createDataType; +import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementOperation.createDataTypeDefinitionWithName; + +import fj.data.Either; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; @@ -29,36 +36,55 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; - import javax.servlet.ServletContext; - +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import org.openecomp.sdc.be.auditing.api.IAuditingManager; +import org.openecomp.sdc.be.auditing.api.AuditEventFactory; +import org.openecomp.sdc.be.auditing.impl.AuditingManager; +import org.openecomp.sdc.be.auditing.impl.resourceadmin.AuditImportResourceAdminEventFactory; +import org.openecomp.sdc.be.components.csar.CsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.ImportUtils.Constants; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; -import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaTagNamesEnum; +import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; +import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.AttributeDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.CsarInfo; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.DefaultUploadResourceInfo; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.NodeTypesMetadataList; +import org.openecomp.sdc.be.model.NullNodeTypeMetadata; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.Resource; @@ -66,905 +92,1023 @@ import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; -import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; +import org.openecomp.sdc.be.model.mapper.NodeTypeMetadataMapper; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation; -import org.openecomp.sdc.be.model.operations.impl.ResourceOperation; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; -import org.openecomp.sdc.common.config.EcompErrorName; -import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.CommonAuditData; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum; +import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.common.util.ThreadLocalsHolder; import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; import org.yaml.snakeyaml.Yaml; -import fj.data.Either; - -@Component("resourceImportManager") +@org.springframework.stereotype.Component("resourceImportManager") public class ResourceImportManager { - private ServletContext servletContext; - - @Autowired - private IAuditingManager auditingManager; - - @Autowired - private ResourceBusinessLogic resourceBusinessLogic; - - @Autowired - private IGraphLockOperation graphLockOperation; - - @Autowired - protected ComponentsUtils componentsUtils; - - @Autowired - protected ResourceOperation resourceOperation; - - public final static Pattern PROPERTY_NAME_PATTERN_IGNORE_LENGTH = Pattern - .compile("[\\w\\-\\_\\d\\:]+"); - @Autowired - protected CapabilityTypeOperation capabilityTypeOperation; - @Autowired - protected ToscaOperationFacade toscaOperationFacade; - - private ResponseFormatManager responseFormatManager; - - private static Logger log = LoggerFactory.getLogger(ResourceImportManager.class.getName()); - - public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) { - this.toscaOperationFacade = toscaOperationFacade; - } - - public Either, ResponseFormat> importNormativeResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, boolean createNewVersion, boolean needLock) { - - LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction(); - lifecycleChangeInfo.setUserRemarks("certification on import"); - Function> validator = (resource) -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); - - return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null, false, null); - } - - public Either, ResponseFormat> importNormativeResourceFromCsar(String resourceYml, UploadResourceInfo resourceMetaData, User creator, boolean createNewVersion, boolean needLock) { - - LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction(); - lifecycleChangeInfo.setUserRemarks("certification on import"); - Function> validator = (resource) -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); - - return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null, false, null); - } - - public Either, ResponseFormat> importCertifiedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, Function> validationFunction, - LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean isInTransaction, boolean createNewVersion, boolean needLock, Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed, CsarInfo csarInfo) { - Resource resource = new Resource(); - ImmutablePair responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED); - Either, ResponseFormat> response = Either.left(responsePair); - - String latestCertifiedResourceId = null; - try { - boolean shouldBeCertified = nodeTypeArtifactsToHandle == null || nodeTypeArtifactsToHandle.isEmpty(); - setConstantMetaData(resource, shouldBeCertified); - setMetaDataFromJson(resourceMetaData, resource); - - Either validateResourceFromYaml = populateResourceFromYaml(resourceYml, resource, isInTransaction); - if (validateResourceFromYaml.isRight()) { - ResponseFormat validationErrorResponse = validateResourceFromYaml.right().value(); - auditErrorImport(resourceMetaData, creator, validationErrorResponse, true); - return Either.right(validationErrorResponse); - - } - - Either isValidResource = validationFunction.apply(resource); - if (isValidResource.isLeft()) { - // The flag createNewVersion if false doesn't create new version - if (!createNewVersion) { - Either latestByName = toscaOperationFacade.getLatestByName(resource.getName()); - if (latestByName.isLeft()) { - return Either.right(componentsUtils.getResponseFormatByResource(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, resource)); - } - } - - response = resourceBusinessLogic.createOrUpdateResourceByImport(resource, creator, true, isInTransaction, needLock, csarInfo); - Either changeStateResponse; - if (response.isLeft()) { - resource = response.left().value().left; - - if(nodeTypeArtifactsToHandle !=null && !nodeTypeArtifactsToHandle.isEmpty()){ - Either, ResponseFormat> handleNodeTypeArtifactsRes = - resourceBusinessLogic.handleNodeTypeArtifacts(resource, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, creator, isInTransaction, false); - if(handleNodeTypeArtifactsRes.isRight()){ - return Either.right(handleNodeTypeArtifactsRes.right().value()); - } - } - latestCertifiedResourceId = getLatestCertifiedResourceId(resource); - changeStateResponse = resourceBusinessLogic.propagateStateToCertified(creator, resource, lifecycleChangeInfo, isInTransaction, needLock, forceCertificationAllowed); - if (changeStateResponse.isRight()) { - response = Either.right(changeStateResponse.right().value()); - } else { - responsePair = new ImmutablePair<>(changeStateResponse.left().value(), response.left().value().right); - response = Either.left(responsePair); - } - } - } else { - ResponseFormat validationErrorResponse = isValidResource.right().value(); - auditErrorImport(resourceMetaData, creator, validationErrorResponse, true); - response = Either.right(validationErrorResponse); - } - - } catch (RuntimeException e) { - ResponseFormat exceptionResponse = handleImportResourceExecption(resourceMetaData, creator, true, e); - response = Either.right(exceptionResponse); - } finally { - if (latestCertifiedResourceId != null && needLock) { - log.debug("unlock resource {}", latestCertifiedResourceId); - graphLockOperation.unlockComponent(latestCertifiedResourceId, NodeTypeEnum.Resource); - } - } - - return response; - } - - private String getLatestCertifiedResourceId(Resource resource) { - Map allVersions = resource.getAllVersions(); - Double latestCertifiedVersion = 0.0; - if (allVersions != null) { - for (String version : allVersions.keySet()) { - Double dVersion = Double.valueOf(version); - if ((dVersion > latestCertifiedVersion) && (version.endsWith(".0"))) { - latestCertifiedVersion = dVersion; - } - } - return allVersions.get(String.valueOf(latestCertifiedVersion)); - } else { - return null; - } - } - - public Either, ResponseFormat> importUserDefinedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, boolean isReusable, boolean isInTransaction) { - - Resource resource = new Resource(); - ImmutablePair responsePair = new ImmutablePair(resource, ActionStatus.CREATED); - Either, ResponseFormat> response = Either.left(responsePair); - - try { - setMetaDataFromJson(resourceMetaData, resource); - - Either validateResourceFromYaml = populateResourceFromYaml(resourceYml, resource, isInTransaction); - if (validateResourceFromYaml.isRight()) { - ResponseFormat validationErrorResponse = validateResourceFromYaml.right().value(); - auditErrorImport(resourceMetaData, creator, validationErrorResponse, false); - return Either.right(validationErrorResponse); - - } - - // currently import VF isn't supported. In future will be supported - // import VF only with CSER file!! - if (ResourceTypeEnum.VF.equals(resource.getResourceType())) { - log.debug("Now import VF isn't supported. It will be supported in future with CSER file only"); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); - } - - Either validateDerivedFromNotEmpty = resourceBusinessLogic.validateDerivedFromNotEmpty(creator, resource, AuditingActionEnum.CREATE_RESOURCE); - if (validateDerivedFromNotEmpty.isRight()) { - return Either.right(validateDerivedFromNotEmpty.right().value()); - } - - Either validatePropertiesTypes = resourceBusinessLogic.validatePropertiesDefaultValues(resource); - - if (validatePropertiesTypes.isLeft()) { - response = resourceBusinessLogic.createOrUpdateResourceByImport(resource, creator, false, isInTransaction, true, null); - } else { - ResponseFormat validationErrorResponse = validatePropertiesTypes.right().value(); - auditErrorImport(resourceMetaData, creator, validationErrorResponse, false); - response = Either.right(validationErrorResponse); - } - - } catch (RuntimeException e) { - ResponseFormat exceptionResponse = handleImportResourceExecption(resourceMetaData, creator, false, e); - response = Either.right(exceptionResponse); - } - - return response; - - } - - Either populateResourceFromYaml(String resourceYml, Resource resource, boolean inTransaction) { - @SuppressWarnings("unchecked") - Either eitherResult = Either.left(true); - Map toscaJsonAll = (Map) new Yaml().load(resourceYml); - Map toscaJson = toscaJsonAll; - - // Checks if exist and builds the node_types map - if (toscaJsonAll.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName()) && resource.getResourceType()!=ResourceTypeEnum.CVFC) { - toscaJson = new HashMap(); - toscaJson.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(), toscaJsonAll.get(ToscaTagNamesEnum.NODE_TYPES.getElementName())); - } - // Derived From - Either setDerivedFrom = setDerivedFrom(toscaJson, resource, inTransaction); - if (setDerivedFrom.isRight()) { - return Either.right(setDerivedFrom.right().value()); - } - Resource parentResource = setDerivedFrom.left().value(); - if(StringUtils.isEmpty(resource.getToscaResourceName())) - setToscaResourceName(toscaJson, resource); - setAttributes(toscaJson, resource); - eitherResult = setCapabilities(toscaJson, resource, parentResource); - if (eitherResult.isRight()) - return eitherResult; - eitherResult = setProperties(toscaJson, resource); - if (eitherResult.isRight()) - return eitherResult; - eitherResult = setRequirements(toscaJson, resource, parentResource); - if (eitherResult.isRight()) - return eitherResult; - setInterfaceLifecycle(toscaJson, resource); - - return eitherResult; - } - - private void setToscaResourceName(Map toscaJson, Resource resource) { - Either, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.NODE_TYPES); - if (toscaElement.isLeft() || toscaElement.left().value().size() == 1) { - String toscaResourceName = toscaElement.left().value().keySet().iterator().next(); - resource.setToscaResourceName(toscaResourceName); - } - } - - private void setInterfaceLifecycle(Map toscaJson, Resource resource) { - Either, ResultStatusEnum> toscaInterfaces = ImportUtils.findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.INTERFACES); - if (toscaInterfaces.isLeft()) { - Map jsonInterfaces = toscaInterfaces.left().value(); - Map moduleInterfaces = new HashMap(); - Iterator> interfacesNameValue = jsonInterfaces.entrySet().iterator(); - while (interfacesNameValue.hasNext()) { - Entry interfaceNameValue = interfacesNameValue.next(); - Either eitherInterface = createModuleInterface(interfaceNameValue.getValue()); - if (eitherInterface.isRight()) { - log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(), resource.getName()); - } else { - moduleInterfaces.put(interfaceNameValue.getKey(), eitherInterface.left().value()); - } - - } - if (moduleInterfaces.size() > 0) { - resource.setInterfaces(moduleInterfaces); - } - } - } - - private Either createModuleInterface(Object interfaceJson) { - InterfaceDefinition interf = new InterfaceDefinition(); - Either result = Either.left(interf); - - try { - if (interfaceJson instanceof String) { - String requirementJsonString = (String) interfaceJson; - interf.setType(requirementJsonString); - } else if (interfaceJson instanceof Map) { - Map requirementJsonMap = (Map) interfaceJson; - if (requirementJsonMap.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) { - String type = (String) requirementJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName()); - interf.setType(type); - interf.setUniqueId(type.toLowerCase()); - } - } else { - result = Either.right(ResultStatusEnum.GENERAL_ERROR); - } - - } catch (Exception e) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Import Resource- create interface"); - BeEcompErrorManager.getInstance().logBeSystemError("Import Resource- create interface"); - log.debug("error when creating interface, message:{}", e.getMessage(), e); - result = Either.right(ResultStatusEnum.GENERAL_ERROR); - } - - return result; - } - - private Either setRequirements(Map toscaJson, Resource resource, Resource parentResource) {// Note that parentResource can be null - Either eitherResult = Either.left(true); - Either, ResultStatusEnum> toscaRequirements = ImportUtils.findFirstToscaListElement(toscaJson, ToscaTagNamesEnum.REQUIREMENTS); - if (toscaRequirements.isLeft()) { - List jsonRequirements = toscaRequirements.left().value(); - Map> moduleRequirements = new HashMap>(); - // Checking for name duplication - Set reqNames = new HashSet<>(); - // Getting flattened list of capabilities of parent node - cap name - // to cap type - Either, ResponseFormat> reqName2Type = getReqName2Type(parentResource); - if (reqName2Type.isRight()) { - ResponseFormat responseFormat = reqName2Type.right().value(); - log.debug("Error during setting requirements of imported resource: {}", responseFormat); - return Either.right(responseFormat); - } - Map reqName2TypeMap = reqName2Type.left().value(); - for (Object jsonRequirementObj : jsonRequirements) { - // Requirement - Map requirementJsonWrapper = (Map) jsonRequirementObj; - String requirementName = requirementJsonWrapper.keySet().iterator().next(); - String reqNameLowerCase = requirementName.toLowerCase(); - if (reqNames.contains(reqNameLowerCase)) { - log.debug("More than one requirement with same name {} (case-insensitive) in imported TOSCA file is invalid", reqNameLowerCase); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "requirement", reqNameLowerCase)); - } - reqNames.add(reqNameLowerCase); - Either eitherRequirement = createRequirementFromImportFile(requirementJsonWrapper.get(requirementName)); - if (eitherRequirement.isRight()) { - log.info("error when creating Requirement:{}, for resource:{}", requirementName, resource.getName()); - return Either.right(eitherRequirement.right().value()); - } - RequirementDefinition requirementDef = eitherRequirement.left().value(); - requirementDef.setName(requirementName); - if (moduleRequirements.containsKey(requirementDef.getCapability())) { - moduleRequirements.get(requirementDef.getCapability()).add(requirementDef); - } else { - List list = new ArrayList(); - list.add(requirementDef); - moduleRequirements.put(requirementDef.getCapability(), list); - } - - // Validating against req/cap of "derived from" node - Either validateVsParentCap = validateCapNameVsDerived(reqName2TypeMap, requirementDef.getCapability(), requirementDef.getName()); - if (validateVsParentCap.isRight()) { - return Either.right(validateVsParentCap.right().value()); - } - if (!validateVsParentCap.left().value()) { - log.debug("Requirement with name {} already exists in parent {}", requirementDef.getName(), parentResource.getName()); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED, "requirement", requirementDef.getName().toLowerCase(), parentResource.getName()); - return Either.right(responseFormat); - } - } - if (moduleRequirements.size() > 0) { - resource.setRequirements(moduleRequirements); - } - - } - return eitherResult; - - } - - private Either createRequirementFromImportFile(Object requirementJson) { - RequirementDefinition requirement = new RequirementDefinition(); - Either result = Either.left(requirement); - - try { - if (requirementJson instanceof String) { - String requirementJsonString = (String) requirementJson; - requirement.setCapability(requirementJsonString); - } else if (requirementJson instanceof Map) { - Map requirementJsonMap = (Map) requirementJson; - if (requirementJsonMap.containsKey(ToscaTagNamesEnum.CAPABILITY.getElementName())) { - requirement.setCapability((String) requirementJsonMap.get(ToscaTagNamesEnum.CAPABILITY.getElementName())); - } - - if (requirementJsonMap.containsKey(ToscaTagNamesEnum.NODE.getElementName())) { - requirement.setNode((String) requirementJsonMap.get(ToscaTagNamesEnum.NODE.getElementName())); - } - - if (requirementJsonMap.containsKey(ToscaTagNamesEnum.RELATIONSHIP.getElementName())) { - requirement.setRelationship((String) requirementJsonMap.get(ToscaTagNamesEnum.RELATIONSHIP.getElementName())); - } - if (requirementJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) { - List occurrencesList = (List) requirementJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName()); - Either validateAndSetOccurrencesStatus = validateOccurrences(occurrencesList); - if (validateAndSetOccurrencesStatus.isRight()) { - result = Either.right(validateAndSetOccurrencesStatus.right().value()); - return result; - } - if (validateAndSetOccurrencesStatus.left().value() == true) { - requirement.setMinOccurrences(occurrencesList.get(0).toString()); - requirement.setMaxOccurrences(occurrencesList.get(1).toString()); - } - - } - } else { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); - } - - } catch (Exception e) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Import Resource - create Requirement"); - BeEcompErrorManager.getInstance().logBeSystemError("Import Resource - create Requirement"); - log.debug("error when creating requirement, message:{}", e.getMessage(), e); - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); - } - - return result; - } - - private Either setProperties(Map toscaJson, Resource resource) { - Map reducedToscaJson = new HashMap<>(toscaJson); - ImportUtils.removeElementFromJsonMap(reducedToscaJson, "capabilities"); - Either result = Either.left(true); - Either, ResultStatusEnum> properties = ImportUtils.getProperties(reducedToscaJson); - if (properties.isLeft()) { - List propertiesList = new ArrayList<>(); - Map value = properties.left().value(); - if (value != null) { - for (Entry entry : value.entrySet()) { - String name = entry.getKey(); - if(!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()){ - log.debug("The property with invalid name {} occured upon import resource {}. ", name, resource.getName()); - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME, JsonPresentationFields.PROPERTY))); - } - PropertyDefinition propertyDefinition = entry.getValue(); - propertyDefinition.setName(name); - propertiesList.add(propertyDefinition); - } - } - resource.setProperties(propertiesList); - } else if(properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND){ - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(properties.right().value(), JsonPresentationFields.PROPERTY))); - } - return result; - } - - private ResultStatusEnum setAttributes(Map toscaJson, Resource resource) { - ResultStatusEnum result = ResultStatusEnum.OK; - Either, ResultStatusEnum> attributes = ImportUtils.getAttributes(toscaJson); - if (attributes.isLeft()) { - List attributeList = new ArrayList<>(); - Map value = attributes.left().value(); - if (value != null) { - for (Entry entry : value.entrySet()) { - String name = entry.getKey(); - PropertyDefinition attributeDef = entry.getValue(); - attributeDef.setName(name); - attributeList.add(attributeDef); - } - } - resource.setAttributes(attributeList); - } else { - result = attributes.right().value(); - } - return result; - } - - private Either setDerivedFrom(Map toscaJson, Resource resource, boolean inTransaction) { - Either toscaDerivedFromElement = ImportUtils.findFirstToscaStringElement(toscaJson, ToscaTagNamesEnum.DERIVED_FROM); - Resource derivedFromResource = null; - if (toscaDerivedFromElement.isLeft()) { - String derivedFrom = toscaDerivedFromElement.left().value(); - log.debug("Derived from TOSCA name is {}", derivedFrom); - resource.setDerivedFrom(Arrays.asList(new String[] { derivedFrom })); - Either latestByToscaResourceName = toscaOperationFacade.getLatestByToscaResourceName(derivedFrom); - - if (latestByToscaResourceName.isRight()) { - StorageOperationStatus operationStatus = latestByToscaResourceName.right().value(); - if (operationStatus.equals(StorageOperationStatus.NOT_FOUND)) { - operationStatus = StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND; - } - log.debug("Error when fetching parent resource {}, error: {}", derivedFrom, operationStatus); - ActionStatus convertFromStorageResponse = componentsUtils.convertFromStorageResponse(operationStatus); - BeEcompErrorManager.getInstance().logBeComponentMissingError("Import TOSCA YAML", "resource", derivedFrom); - return Either.right(componentsUtils.getResponseFormat(convertFromStorageResponse, derivedFrom)); - } - derivedFromResource = latestByToscaResourceName.left().value(); - } - return Either.left(derivedFromResource); - } - - private Either setCapabilities(Map toscaJson, Resource resource, Resource parentResource) {// Note that parentResource can be null - Either eitherResult = Either.left(true); - Either, ResultStatusEnum> toscaCapabilities = ImportUtils.findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.CAPABILITIES); - if (toscaCapabilities.isLeft()) { - Map jsonCapabilities = toscaCapabilities.left().value(); - Map> moduleCapabilities = new HashMap>(); - Iterator> capabilitiesNameValue = jsonCapabilities.entrySet().iterator(); - Set capNames = new HashSet<>(); - // Getting flattened list of capabilities of parent node - cap name - // to cap type - Either, ResponseFormat> capName2Type = getCapName2Type(parentResource); - if (capName2Type.isRight()) { - ResponseFormat responseFormat = capName2Type.right().value(); - log.debug("Error during setting capabilities of imported resource: {}", responseFormat); - return Either.right(responseFormat); - } - Map capName2TypeMap = capName2Type.left().value(); - while (capabilitiesNameValue.hasNext()) { - Entry capabilityNameValue = capabilitiesNameValue.next(); - - // Validating that no req/cap duplicates exist in imported YAML - String capNameLowerCase = capabilityNameValue.getKey().toLowerCase(); - if (capNames.contains(capNameLowerCase)) { - log.debug("More than one capability with same name {} (case-insensitive) in imported TOSCA file is invalid", capNameLowerCase); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "capability", capNameLowerCase)); - } - capNames.add(capNameLowerCase); - - Either eitherCapability = createCapabilityFromImportFile(capabilityNameValue.getValue()); - if (eitherCapability.isRight()) { - log.debug("error when creating capability:{}, for resource:{}", capabilityNameValue.getKey(), resource.getName()); - return Either.right(eitherCapability.right().value()); - } - - CapabilityDefinition capabilityDef = eitherCapability.left().value(); - capabilityDef.setName(capabilityNameValue.getKey()); - if (moduleCapabilities.containsKey(capabilityDef.getType())) { - moduleCapabilities.get(capabilityDef.getType()).add(capabilityDef); - } else { - List list = new ArrayList(); - list.add(capabilityDef); - moduleCapabilities.put(capabilityDef.getType(), list); - } - - // Validating against req/cap of "derived from" node - Either validateVsParentCap = validateCapNameVsDerived(capName2TypeMap, capabilityDef.getType(), capabilityDef.getName()); - if (validateVsParentCap.isRight()) { - return Either.right(validateVsParentCap.right().value()); - } - if (!validateVsParentCap.left().value()) { - // Here parentResource is for sure not null, so it's - // null-safe - log.debug("Capability with name {} already exists in parent {}", capabilityDef.getName(), parentResource.getName()); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED, "capability", capabilityDef.getName().toLowerCase(), parentResource.getName()); - return Either.right(responseFormat); - } - } - if (moduleCapabilities.size() > 0) { - resource.setCapabilities(moduleCapabilities); - } - } - - return eitherResult; - - } - - private Either, ResponseFormat> getCapName2Type(Resource parentResource) { - Map capName2type = new HashMap<>(); - if (parentResource != null) { - Map> capabilities = parentResource.getCapabilities(); - if (capabilities != null) { - for (List capDefinitions : capabilities.values()) { - for (CapabilityDefinition capDefinition : capDefinitions) { - String nameLowerCase = capDefinition.getName().toLowerCase(); - if (capName2type.get(nameLowerCase) != null) { - String parentResourceName = parentResource.getName(); - log.debug("Resource with name {} has more than one capability with name {}, ignoring case", parentResourceName, nameLowerCase); - BeEcompErrorManager.getInstance().logInternalDataError("Import resource", "Parent resource " + parentResourceName + " of imported resource has one or more capabilities with name " + nameLowerCase, ErrorSeverity.ERROR); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); - } - capName2type.put(nameLowerCase, capDefinition.getType()); - } - } - } - } - return Either.left(capName2type); - } - - private Either, ResponseFormat> getReqName2Type(Resource parentResource) { - Map reqName2type = new HashMap<>(); - if (parentResource != null) { - Map> requirements = parentResource.getRequirements(); - if (requirements != null) { - for (List reqDefinitions : requirements.values()) { - for (RequirementDefinition reqDefinition : reqDefinitions) { - String nameLowerCase = reqDefinition.getName().toLowerCase(); - if (reqName2type.get(nameLowerCase) != null) { - String parentResourceName = parentResource.getName(); - log.debug("Resource with name {} has more than one requirement with name {}, ignoring case", parentResourceName, nameLowerCase); - BeEcompErrorManager.getInstance().logInternalDataError("Import resource", "Parent resource " + parentResourceName + " of imported resource has one or more requirements with name " + nameLowerCase, ErrorSeverity.ERROR); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); - } - reqName2type.put(nameLowerCase, reqDefinition.getCapability()); - } - } - } - } - return Either.left(reqName2type); - } - - private Either validateCapNameVsDerived(Map parentCapName2Type, String childCapabilityType, String reqCapName) { - String capNameLowerCase = reqCapName.toLowerCase(); - log.trace("Validating capability {} vs parent resource", capNameLowerCase); - String parentCapType = parentCapName2Type.get(capNameLowerCase); - if (parentCapType != null) { - if (childCapabilityType.equals(parentCapType)) { - log.debug("Capability with name {} is of same type {} for imported resource and its parent - this is OK", capNameLowerCase, childCapabilityType); - return Either.left(true); - } - Either capabilityTypeDerivedFrom = capabilityTypeOperation.isCapabilityTypeDerivedFrom(childCapabilityType, parentCapType); - if (capabilityTypeDerivedFrom.isRight()) { - log.debug("Couldn't check whether imported resource capability derives from its parent's capability"); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(capabilityTypeDerivedFrom.right().value())); - return Either.right(responseFormat); - } - return Either.left(capabilityTypeDerivedFrom.left().value()); - } - return Either.left(true); - } - - private Either createCapabilityFromImportFile(Object capabilityJson) { - - CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); - Either result = Either.left(capabilityDefinition); - - try { - if (capabilityJson instanceof String) { - String capabilityJsonString = (String) capabilityJson; - capabilityDefinition.setType(capabilityJsonString); - } else if (capabilityJson instanceof Map) { - Map capabilityJsonMap = (Map) capabilityJson; - // Type - if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) { - capabilityDefinition.setType((String) capabilityJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName())); - } - // ValidSourceTypes - if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) { - capabilityDefinition.setValidSourceTypes((List) capabilityJsonMap.get(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())); - } - // ValidSourceTypes - if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.DESCRIPTION.getElementName())) { - capabilityDefinition.setDescription((String) capabilityJsonMap.get(ToscaTagNamesEnum.DESCRIPTION.getElementName())); - } - if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) { - List occurrencesList = (List) capabilityJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName()); - Either validateAndSetOccurrencesStatus = validateOccurrences(occurrencesList); - if (validateAndSetOccurrencesStatus.isRight()) { - result = Either.right(validateAndSetOccurrencesStatus.right().value()); - return result; - } - if (validateAndSetOccurrencesStatus.left().value() == true) { - capabilityDefinition.setMinOccurrences(occurrencesList.get(0).toString()); - capabilityDefinition.setMaxOccurrences(occurrencesList.get(1).toString()); - } - } - if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.PROPERTIES.getElementName())) { - - Either, ResultStatusEnum> propertiesRes = ImportUtils.getProperties(capabilityJsonMap); - if (propertiesRes.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND)); - return result; - } else { - propertiesRes.left().value().entrySet().stream().forEach(e -> e.getValue().setName(e.getKey().toLowerCase())); - List capabilityProperties = propertiesRes.left().value().values().stream().map(p -> new ComponentInstanceProperty(p, p.getDefaultValue(), null)).collect(Collectors.toList()); - capabilityDefinition.setProperties(capabilityProperties); - } - } - } else if (!(capabilityJson instanceof List)) { - - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); - - } - } catch (Exception e) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Import Resource - create capability"); - BeEcompErrorManager.getInstance().logBeSystemError("Import Resource - create capability"); - log.debug("error when creating capability, message:{}", e.getMessage(), e); - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); - } - - return result; - } - - private ResponseFormat handleImportResourceExecption(UploadResourceInfo resourceMetaData, User user, boolean isNormative, RuntimeException e) { - String payloadName = (resourceMetaData != null) ? resourceMetaData.getPayloadName() : ""; - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Import Resource " + payloadName); - BeEcompErrorManager.getInstance().logBeSystemError("Import Resource " + payloadName); - - log.debug("Error when importing resource from payload:{} Exception text: {}", payloadName, e.getMessage(), e); - ResponseFormat errorResponseWrapper = getResponseFormatManager().getResponseFormat(ActionStatus.GENERAL_ERROR); - auditErrorImport(resourceMetaData, user, errorResponseWrapper, isNormative); - return errorResponseWrapper; - } - - private void auditErrorImport(UploadResourceInfo resourceMetaData, User user, ResponseFormat errorResponseWrapper, boolean isNormative) { - EnumMap auditingFields = new EnumMap<>(AuditingFieldsKeysEnum.class); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_ACTION, AuditingActionEnum.IMPORT_RESOURCE.getName()); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceMetaData.getName()); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_TYPE, ComponentTypeEnum.RESOURCE.getValue()); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_VERSION, ""); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_UID, user.getUserId()); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_STATE, ""); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, ""); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_STATUS, errorResponseWrapper.getStatus()); - String message = ""; - if (errorResponseWrapper.getMessageId() != null) { - message = errorResponseWrapper.getMessageId() + ": "; - } - message += errorResponseWrapper.getFormattedMessage(); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_DESC, message); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_NAME, user.getFirstName() + " " + user.getLastName()); - - String version, lifeCycleState; - if (isNormative) { - version = Constants.FIRST_CERTIFIED_VERSION_VERSION; - lifeCycleState = LifecycleStateEnum.CERTIFIED.name(); - } else { - version = ""; - lifeCycleState = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name(); - - } - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, version); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE, lifeCycleState); - auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_TOSCA_NODE_TYPE, ""); - - getAuditingManager().auditEvent(auditingFields); - } - - private void setMetaDataFromJson(UploadResourceInfo resourceMetaData, Resource resource) { - resource.setTags(resourceMetaData.getTags()); - List categories = resourceMetaData.getCategories(); - resource.setCategories(categories); - resource.setDescription(resourceMetaData.getDescription()); - resource.setIcon(resourceMetaData.getResourceIconPath()); - resource.setName(resourceMetaData.getName()); - if (categories != null && !categories.isEmpty()) { - CategoryDefinition categoryDef = categories.get(0); - resource.setAbstract(false); - if (categoryDef != null && categoryDef.getName() != null && categoryDef.getName().equals(Constants.ABSTRACT_CATEGORY_NAME)) { - SubCategoryDefinition subCategoryDef = categoryDef.getSubcategories().get(0); - if (subCategoryDef != null && subCategoryDef.getName().equals(Constants.ABSTRACT_SUBCATEGORY)) { - resource.setAbstract(true); - } - } - } - resource.setContactId(resourceMetaData.getContactId()); - resource.setCreatorUserId(resourceMetaData.getContactId()); - - if (resourceMetaData.getVendorName() != null) { - resource.setVendorName(resourceMetaData.getVendorName()); - } - - if (resourceMetaData.getVendorRelease() != null) { - resource.setVendorRelease(resourceMetaData.getVendorRelease()); - } - - resource.setResourceType(ResourceTypeEnum.valueOf(resourceMetaData.getResourceType())); - - } - - private void setConstantMetaData(Resource resource, boolean shouldBeCertified) { - String version; - LifecycleStateEnum state; - if(shouldBeCertified){ - version = ImportUtils.Constants.FIRST_CERTIFIED_VERSION_VERSION; - state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE; - }else{ - version = ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION; - state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT; - } - resource.setVersion(version); - resource.setLifecycleState(state); - resource.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION); - resource.setVendorName(ImportUtils.Constants.VENDOR_NAME); - resource.setVendorRelease(ImportUtils.Constants.VENDOR_RELEASE); - - } - - private Either validateOccurrences(List occurrensesList) { - - if (!ValidationUtils.validateListNotEmpty(occurrensesList)) { - log.debug("Occurrenses list empty"); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - - if (occurrensesList.size() < 2) { - log.debug("Occurrenses list size not 2"); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - Object minObj = occurrensesList.get(0); - Object maxObj = occurrensesList.get(1); - Integer minOccurrences = null; - Integer maxOccurrences = null; - if (minObj instanceof Integer) - minOccurrences = (Integer) minObj; - else { - log.debug("Invalid occurrenses format. low_bound occurrense must be Integer {}", minObj); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - if (minOccurrences < 0) { - log.debug("Invalid occurrenses format.low_bound occurrense negative {}", minOccurrences); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - - if (maxObj instanceof String) { - if (maxObj.equals("UNBOUNDED")) { - return Either.left(true); - } else { - log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - } else { - if (maxObj instanceof Integer) - maxOccurrences = (Integer) maxObj; - else { - log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - - if (maxOccurrences <= 0 || maxOccurrences < minOccurrences) { - log.debug("Invalid occurrenses format. min occurrence is {}, Max occurrence is {}", minOccurrences, maxOccurrences); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); - return Either.right(responseFormat); - } - } - - return Either.left(true); - - } - - public void init(ServletContext servletContext) { - if (this.servletContext == null) { - synchronized (this) { - if (this.servletContext == null) { - this.servletContext = servletContext; - responseFormatManager = ResponseFormatManager.getInstance(); - resourceBusinessLogic = getResourceBL(servletContext); - } - } - } - } - - public boolean isResourceExist(String resourceName) { - return resourceBusinessLogic.isResourceExist(resourceName); - } - - private ResourceBusinessLogic getResourceBL(ServletContext context) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); - ResourceBusinessLogic resourceBl = webApplicationContext.getBean(ResourceBusinessLogic.class); - return resourceBl; - } - - public ServletContext getServletContext() { - return servletContext; - } - - public IAuditingManager getAuditingManager() { - return auditingManager; - } - - public ResponseFormatManager getResponseFormatManager() { - return responseFormatManager; - } - - public void setResponseFormatManager(ResponseFormatManager responseFormatManager) { - this.responseFormatManager = responseFormatManager; - } - - public ResourceBusinessLogic getResourceBusinessLogic() { - return resourceBusinessLogic; - } - - public void setResourceBusinessLogic(ResourceBusinessLogic resourceBusinessLogic) { - this.resourceBusinessLogic = resourceBusinessLogic; - } - - public Logger getLog() { - return log; - } - - public static void setLog(Logger log) { - ResourceImportManager.log = log; - } - - public IGraphLockOperation getGraphLockOperation() { - return graphLockOperation; - } - - public void setGraphLockOperation(IGraphLockOperation graphLockOperation) { - this.graphLockOperation = graphLockOperation; - } - - public void setServletContext(ServletContext servletContext) { - this.servletContext = servletContext; - } - - public void setAuditingManager(IAuditingManager auditingManager) { - this.auditingManager = auditingManager; - } - - public void setResourceOperation(ResourceOperation resourceOperation) { - this.resourceOperation = resourceOperation; - } - + static final Pattern PROPERTY_NAME_PATTERN_IGNORE_LENGTH = Pattern.compile("['\\w\\s\\-\\.\\:]+"); + private static final Logger log = Logger.getLogger(ResourceImportManager.class); + private final InterfaceDefinitionHandler interfaceDefinitionHandler; + private final ComponentsUtils componentsUtils; + private final CapabilityTypeOperation capabilityTypeOperation; + private final JanusGraphDao janusGraphDao; + private ServletContext servletContext; + private AuditingManager auditingManager; + private ResourceBusinessLogic resourceBusinessLogic; + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; + private IGraphLockOperation graphLockOperation; + private ToscaOperationFacade toscaOperationFacade; + private ResponseFormatManager responseFormatManager; + + @Autowired + public ResourceImportManager(final ComponentsUtils componentsUtils, final CapabilityTypeOperation capabilityTypeOperation, + final InterfaceDefinitionHandler interfaceDefinitionHandler, final JanusGraphDao janusGraphDao) { + this.componentsUtils = componentsUtils; + this.capabilityTypeOperation = capabilityTypeOperation; + this.interfaceDefinitionHandler = interfaceDefinitionHandler; + this.janusGraphDao = janusGraphDao; + } + + public ServiceBusinessLogic getServiceBusinessLogic() { + return serviceBusinessLogic; + } + + public void setServiceBusinessLogic(ServiceBusinessLogic serviceBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; + } + + @Autowired + public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) { + this.toscaOperationFacade = toscaOperationFacade; + } + + public ImmutablePair importNormativeResource(final String resourceYml, final UploadResourceInfo resourceMetaData, + final User creator, final boolean createNewVersion, final boolean needLock, + final boolean isInTransaction) { + LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction(); + lifecycleChangeInfo.setUserRemarks("certification on import"); + Function validator = resource -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); + return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, isInTransaction, createNewVersion, + needLock, null, null, false, null, null, false); + } + + public void importAllNormativeResource(final String resourcesYaml, final NodeTypesMetadataList nodeTypesMetadataList, final User user, + final boolean createNewVersion, final boolean needLock) { + final Map nodeTypesYamlMap; + try { + nodeTypesYamlMap = new Yaml().load(resourcesYaml); + } catch (final Exception e) { + log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceImportManager.class.getName(), "Could not parse node types YAML", e); + throw new ByActionStatusComponentException(ActionStatus.INVALID_NODE_TYPES_YAML); + } + if (!nodeTypesYamlMap.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName())) { + return; + } + final Map nodeTypesMap = (Map) nodeTypesYamlMap.get(ToscaTagNamesEnum.NODE_TYPES.getElementName()); + importAllNormativeResource(nodeTypesMap, nodeTypesMetadataList, user, "", createNewVersion,needLock); + } + + public void importAllNormativeResource(final Map nodeTypesMap, final NodeTypesMetadataList nodeTypesMetadataList, + final User user, String model, final boolean createNewVersion, final boolean needLock) { + try { + nodeTypesMetadataList.getNodeMetadataList().forEach(nodeTypeMetadata -> { + final String nodeTypeToscaName = nodeTypeMetadata.getToscaName(); + final Map nodeTypeMap = (Map) nodeTypesMap.get(nodeTypeToscaName); + if (nodeTypeMap == null) { + log.warn(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceImportManager.class.getName(), + "Could not find given node type '{}'. The node will not be created.", nodeTypeToscaName); + } else { + final Map>> nodeTypeDefinitionMap = + Map.of(ToscaTagNamesEnum.NODE_TYPES.getElementName(), + Map.of(nodeTypeToscaName, nodeTypeMap) + ); + final String nodeTypeYaml = new Yaml().dump(nodeTypeDefinitionMap); + UploadResourceInfo uploadResourceInfo = NodeTypeMetadataMapper.mapTo(nodeTypeMetadata); + if (uploadResourceInfo instanceof DefaultUploadResourceInfo) { + uploadResourceInfo.setModel(model); + uploadResourceInfo.setContactId(user.getUserId()); + } + importNormativeResource(nodeTypeYaml, uploadResourceInfo, user, createNewVersion, needLock, true); + } + }); + janusGraphDao.commit(); + } catch (final Exception e) { + janusGraphDao.rollback(); + throw e; + } + } + + public ImmutablePair importCertifiedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, + Function validationFunction, + LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean isInTransaction, + boolean createNewVersion, boolean needLock, + Map> nodeTypeArtifactsToHandle, + List nodeTypesNewCreatedArtifacts, + boolean forceCertificationAllowed, CsarInfo csarInfo, String nodeName, + boolean isNested) { + Resource resource = new Resource(); + ImmutablePair responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED); + Either, ResponseFormat> response = Either.left(responsePair); + String latestCertifiedResourceId = null; + try { + boolean shouldBeCertified = nodeTypeArtifactsToHandle == null || nodeTypeArtifactsToHandle.isEmpty(); + setConstantMetaData(resource, shouldBeCertified); + setResourceMetaData(resource, resourceYml, resourceMetaData); + populateResourceFromYaml(resourceYml, resource); + validationFunction.apply(resource); + resource.getComponentMetadataDefinition().getMetadataDataDefinition().setNormative(resourceMetaData.isNormative()); + checkResourceExists(createNewVersion, csarInfo, resource); + resource = resourceBusinessLogic + .createOrUpdateResourceByImport(resource, creator, true, isInTransaction, needLock, csarInfo, nodeName, isNested).left; + Resource changeStateResponse; + if (nodeTypeArtifactsToHandle != null && !nodeTypeArtifactsToHandle.isEmpty()) { + Either, ResponseFormat> handleNodeTypeArtifactsRes = resourceBusinessLogic + .handleNodeTypeArtifacts(resource, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, creator, isInTransaction, false); + if (handleNodeTypeArtifactsRes.isRight()) { + //TODO: should be used more correct action + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + } + latestCertifiedResourceId = getLatestCertifiedResourceId(resource); + changeStateResponse = resourceBusinessLogic + .propagateStateToCertified(creator, resource, lifecycleChangeInfo, isInTransaction, needLock, forceCertificationAllowed); + responsePair = new ImmutablePair<>(changeStateResponse, response.left().value().right); + } catch (RuntimeException e) { + handleImportResourceException(resourceMetaData, creator, true, e); + } finally { + if (latestCertifiedResourceId != null && needLock) { + log.debug("unlock resource {}", latestCertifiedResourceId); + graphLockOperation.unlockComponent(latestCertifiedResourceId, NodeTypeEnum.Resource); + } + } + return responsePair; + } + + private void checkResourceExists(final boolean isCreate, final CsarInfo csarInfo, final Resource resource) { + if (isCreate) { + checkResourceExistsOnCreate(resource, csarInfo); + } else { + checkResourceExistsOnUpdate(resource); + } + } + + private void checkResourceExistsOnCreate(final Resource resource, final CsarInfo csarInfo) { + if (isCsarPresent(csarInfo)) { + return; + } + final Either resourceEither = + toscaOperationFacade.getComponentByNameAndVendorRelease(resource.getComponentType(), resource.getName(), + resource.getVendorRelease(), JsonParseFlagEnum.ParseAll, resource.getModel()); + if (resourceEither.isLeft() && toscaOperationFacade.isNodeAssociatedToModel(resource.getModel(), resource)) { + if (resource.getModel() == null) { + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS, + resource.getName(), resource.getVendorRelease()); + } + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS_IN_MODEL, + resource.getName(), resource.getVendorRelease(), resource.getModel()); + } + } + + private void checkResourceExistsOnUpdate(final Resource resource) { + final String model = resource.getModel(); + final Either latestByName = toscaOperationFacade.getLatestByName(resource.getName(), model); + if (latestByName.isLeft() && toscaOperationFacade.isNodeAssociatedToModel(model, resource)) { + if (model == null) { + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, + resource.getResourceType().name(), resource.getName()); + } + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_WITH_MODEL_ALREADY_EXIST, resource.getName(), model); + } + } + + private boolean isCsarPresent(final CsarInfo csarInfo) { + return csarInfo != null && StringUtils.isNotEmpty(csarInfo.getCsarUUID()); + } + + private String getLatestCertifiedResourceId(Resource resource) { + Map allVersions = resource.getAllVersions(); + Double latestCertifiedVersion = 0.0; + if (allVersions != null) { + for (String version : allVersions.keySet()) { + Double dVersion = Double.valueOf(version); + if ((dVersion > latestCertifiedVersion) && (version.endsWith(".0"))) { + latestCertifiedVersion = dVersion; + } + } + return allVersions.get(String.valueOf(latestCertifiedVersion)); + } else { + return null; + } + } + + public void populateResourceMetadata(UploadResourceInfo resourceMetaData, Resource resource) { + if (resource != null && resourceMetaData != null) { + resource.setDescription(resourceMetaData.getDescription()); + resource.setTags(resourceMetaData.getTags()); + resource.setCategories(resourceMetaData.getCategories()); + resource.setContactId(resourceMetaData.getContactId()); + resource.setName(resourceMetaData.getName()); + resource.setIcon(resourceMetaData.getResourceIconPath()); + resource.setResourceVendorModelNumber(resourceMetaData.getResourceVendorModelNumber()); + resource.setResourceType(ResourceTypeEnum.valueOf(resourceMetaData.getResourceType())); + resource.setTenant(resourceMetaData.getTenant()); + if (resourceMetaData.getVendorName() != null) { + resource.setVendorName(resourceMetaData.getVendorName()); + } + if (resourceMetaData.getVendorRelease() != null) { + resource.setVendorRelease(resourceMetaData.getVendorRelease()); + } + if (resourceMetaData.getModel() != null) { + resource.setModel(resourceMetaData.getModel()); + } + } + } + + public ImmutablePair importUserDefinedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, + boolean isInTransaction) { + Resource resource = new Resource(); + ImmutablePair responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED); + try { + setMetaDataFromJson(resourceMetaData, resource); + populateResourceFromYaml(resourceYml, resource); + // currently import VF isn't supported. In future will be supported import VF only with CSAR file!! + if (ResourceTypeEnum.VF == resource.getResourceType()) { + log.debug("Now import VF isn't supported. It will be supported in future with CSAR file only"); + throw new ByActionStatusComponentException(ActionStatus.RESTRICTED_OPERATION); + } + resourceBusinessLogic.validateDerivedFromNotEmpty(creator, resource, AuditingActionEnum.CREATE_RESOURCE); + resourceBusinessLogic.validatePropertiesDefaultValues(resource); + responsePair = resourceBusinessLogic.createOrUpdateResourceByImport(resource, creator, false, isInTransaction, true, null, null, false); + } catch (RuntimeException e) { + handleImportResourceException(resourceMetaData, creator, false, e); + } + return responsePair; + } + + private void populateResourceFromYaml(final String resourceYml, Resource resource) { + @SuppressWarnings("unchecked") Object ymlObj = new Yaml().load(resourceYml); + if (ymlObj instanceof Map) { + final Either existingResource = getExistingResource(resource); + final Map toscaJsonAll = (Map) ymlObj; + Map toscaJson = toscaJsonAll; + if (toscaJsonAll.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName()) && resource.getResourceType() != ResourceTypeEnum.CVFC) { + toscaJson = new HashMap<>(); + toscaJson.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(), toscaJsonAll.get(ToscaTagNamesEnum.NODE_TYPES.getElementName())); + } + final List foundElements = new ArrayList<>(); + final Either, ResultStatusEnum> toscaElements = ImportUtils + .findToscaElements(toscaJsonAll, ToscaTagNamesEnum.DATA_TYPES.getElementName(), ToscaElementTypeEnum.MAP, foundElements); + if (toscaElements.isLeft()) { + final Map toscaAttributes = (Map) foundElements.get(0); + if (MapUtils.isNotEmpty(toscaAttributes)) { + resource.setDataTypes(extractDataTypeFromJson(resourceBusinessLogic, toscaAttributes, resource.getModel())); + } + } + final Resource parentResource = setDerivedFrom(toscaJson, resource); + if (StringUtils.isEmpty(resource.getToscaResourceName())) { + setToscaResourceName(toscaJson, resource); + } + setCapabilities(toscaJson, resource, parentResource); + setProperties(toscaJson, resource, existingResource); + setAttributes(toscaJson, resource); + setRequirements(toscaJson, resource, parentResource); + setInterfaceLifecycle(toscaJson, resource, existingResource); + } else { + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + } + + private Either getExistingResource(final Resource resource) { + final Either, JanusGraphOperationStatus> byCriteria = janusGraphDao.getByCriteria( + getVertexTypeEnum(resource.getResourceType()), propertiesToMatch(resource), propertiesToNotMatch(), + JsonParseFlagEnum.ParseAll, resource.getModel(), false); + if (byCriteria.isLeft() && CollectionUtils.isNotEmpty(byCriteria.left().value())) { + final List graphVertexList = byCriteria.left().value(); + if (graphVertexList.size() == 1) { + return toscaOperationFacade.getToscaElement(graphVertexList.get(0).getUniqueId()); + } else { + final Optional vertex = graphVertexList.stream() + .max(Comparator.comparing(graphVertex -> (String) graphVertex.getMetadataProperties().get(GraphPropertyEnum.VERSION))); + if (vertex.isPresent()) { + return toscaOperationFacade.getToscaElement(vertex.get().getUniqueId()); + } + } + } + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + private VertexTypeEnum getVertexTypeEnum(final ResourceTypeEnum resourceType) { + return ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : VertexTypeEnum.TOPOLOGY_TEMPLATE; + } + + private Map propertiesToMatch(final Resource resource) { + final Map graphProperties = new EnumMap<>(GraphPropertyEnum.class); + graphProperties.put(GraphPropertyEnum.NORMALIZED_NAME, ValidationUtils.normaliseComponentName(resource.getName())); + graphProperties.put(GraphPropertyEnum.COMPONENT_TYPE, resource.getComponentType().name()); + graphProperties.put(GraphPropertyEnum.RESOURCE_TYPE, resource.getResourceType().name()); + graphProperties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + return graphProperties; + } + + private Map propertiesToNotMatch() { + final Map graphProperties = new EnumMap<>(GraphPropertyEnum.class); + graphProperties.put(GraphPropertyEnum.IS_DELETED, true); + graphProperties.put(GraphPropertyEnum.IS_ARCHIVED, true); + return graphProperties; + } + + private void setToscaResourceName(Map toscaJson, Resource resource) { + resource.setToscaResourceName(getToscaResourceName(toscaJson)); + } + + private String getToscaResourceName(Map toscaJson) { + Either, ResultStatusEnum> toscaElement = ImportUtils + .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.NODE_TYPES); + if (toscaElement.isLeft() && toscaElement.left().value().size() == 1) { + String toscaResourceName = toscaElement.left().value().keySet().iterator().next(); + return toscaResourceName; + } + return null; + } + + private void setInterfaceLifecycle(Map toscaJson, Resource resource, Either existingResource) { + final Either, ResultStatusEnum> toscaInterfaces = ImportUtils + .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.INTERFACES); + final Map moduleInterfaces = new HashMap<>(); + final Map map; + if (toscaInterfaces.isLeft()) { + map = toscaInterfaces.left().value(); + for (final Entry interfaceNameValue : map.entrySet()) { + final Either eitherInterface = createModuleInterface(interfaceNameValue.getValue(), + resource.getModel()); + if (eitherInterface.isRight()) { + log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(), resource.getName()); + } else { + final InterfaceDefinition interfaceDefinition = eitherInterface.left().value(); + moduleInterfaces.put(interfaceDefinition.getType(), interfaceDefinition); + } + } + } else { + map = Collections.emptyMap(); + } + if (existingResource.isLeft()) { + final Map userCreatedInterfaceDefinitions = + existingResource.left().value().getInterfaces().entrySet().stream() + .filter(i -> i.getValue().isUserCreated()) + .filter(i -> !map.containsKey(i.getValue().getType())) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + if (MapUtils.isNotEmpty(userCreatedInterfaceDefinitions)) { + moduleInterfaces.putAll(userCreatedInterfaceDefinitions); + } + } + + if (MapUtils.isNotEmpty(moduleInterfaces)) { + resource.setInterfaces(moduleInterfaces); + } + } + + private Either createModuleInterface(final Object interfaceJson, final String model) { + try { + if (interfaceJson instanceof String) { + final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); + interfaceDefinition.setType((String) interfaceJson); + return Either.left(interfaceDefinition); + } + if (interfaceJson instanceof Map) { + final Map interfaceJsonMap = (Map) interfaceJson; + final InterfaceDefinition interfaceDefinition = interfaceDefinitionHandler.create(interfaceJsonMap, model); + return Either.left(interfaceDefinition); + } + return Either.right(ResultStatusEnum.GENERAL_ERROR); + } catch (final Exception e) { + BeEcompErrorManager.getInstance().logBeSystemError("Import Resource- create interface"); + log.debug("error when creating interface, message:{}", e.getMessage(), e); + return Either.right(ResultStatusEnum.GENERAL_ERROR); + } + } + + private void setRequirements(Map toscaJson, Resource resource, + Resource parentResource) {// Note that parentResource can be null + Either, ResultStatusEnum> toscaRequirements = ImportUtils + .findFirstToscaListElement(toscaJson, ToscaTagNamesEnum.REQUIREMENTS); + if (toscaRequirements.isLeft()) { + List jsonRequirements = toscaRequirements.left().value(); + Map> moduleRequirements = new HashMap<>(); + // Checking for name duplication + Set reqNames = new HashSet<>(); + // Getting flattened list of capabilities of parent node - cap name to cap type + Map reqName2TypeMap = getReqName2Type(parentResource); + for (Object jsonRequirementObj : jsonRequirements) { + // Requirement + Map requirementJsonWrapper = (Map) jsonRequirementObj; + String requirementName = requirementJsonWrapper.keySet().iterator().next(); + String reqNameLowerCase = requirementName.toLowerCase(); + if (reqNames.contains(reqNameLowerCase)) { + log.debug("More than one requirement with same name {} (case-insensitive) in imported TOSCA file is invalid", reqNameLowerCase); + throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "requirement", reqNameLowerCase); + } + reqNames.add(reqNameLowerCase); + RequirementDefinition requirementDef = createRequirementFromImportFile(requirementJsonWrapper.get(requirementName)); + requirementDef.setName(requirementName); + if (moduleRequirements.containsKey(requirementDef.getCapability())) { + moduleRequirements.get(requirementDef.getCapability()).add(requirementDef); + } else { + List list = new ArrayList<>(); + list.add(requirementDef); + moduleRequirements.put(requirementDef.getCapability(), list); + } + // Validating against req/cap of "derived from" node + Boolean validateVsParentCap = validateCapNameVsDerived(reqName2TypeMap, requirementDef.getCapability(), requirementDef.getName()); + if (!validateVsParentCap) { + String parentResourceName = parentResource != null ? parentResource.getName() : ""; + log.debug("Requirement with name {} already exists in parent {}", requirementDef.getName(), parentResourceName); + throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED, "requirement", + requirementDef.getName().toLowerCase(), parentResourceName); + } + } + if (moduleRequirements.size() > 0) { + resource.setRequirements(moduleRequirements); + } + } + } + + private RequirementDefinition createRequirementFromImportFile(Object requirementJson) { + RequirementDefinition requirement = new RequirementDefinition(); + if (requirementJson instanceof String) { + String requirementJsonString = (String) requirementJson; + requirement.setCapability(requirementJsonString); + } else if (requirementJson instanceof Map) { + Map requirementJsonMap = (Map) requirementJson; + if (requirementJsonMap.containsKey(ToscaTagNamesEnum.CAPABILITY.getElementName())) { + requirement.setCapability((String) requirementJsonMap.get(ToscaTagNamesEnum.CAPABILITY.getElementName())); + } + if (requirementJsonMap.containsKey(ToscaTagNamesEnum.NODE.getElementName())) { + requirement.setNode((String) requirementJsonMap.get(ToscaTagNamesEnum.NODE.getElementName())); + } + if (requirementJsonMap.containsKey(ToscaTagNamesEnum.RELATIONSHIP.getElementName())) { + requirement.setRelationship((String) requirementJsonMap.get(ToscaTagNamesEnum.RELATIONSHIP.getElementName())); + } + if (requirementJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) { + List occurrencesList = (List) requirementJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName()); + validateOccurrences(occurrencesList); + requirement.setMinOccurrences(occurrencesList.get(0).toString()); + requirement.setMaxOccurrences(occurrencesList.get(1).toString()); + } + } else { + throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML); + } + return requirement; + } + + private void setProperties(final Map toscaJson, final Resource resource, + final Either existingResource) { + final Map reducedToscaJson = new HashMap<>(toscaJson); + ImportUtils.removeElementFromJsonMap(reducedToscaJson, "capabilities"); + final Either, ResultStatusEnum> properties = ImportUtils.getProperties(reducedToscaJson); + if (properties.isLeft()) { + final Map propertyDefinitionMap = properties.left().value(); + if (MapUtils.isNotEmpty(propertyDefinitionMap)) { + final List propertiesList = new ArrayList<>(); + for (final Entry entry : propertyDefinitionMap.entrySet()) { + addPropertyToList(resource.getName(), propertiesList, entry); + } + if (existingResource.isLeft()) { + if ( CollectionUtils.isNotEmpty(existingResource.left().value().getProperties())) { + final List userCreatedResourceProperties = + existingResource.left().value().getProperties().stream() + .filter(PropertyDataDefinition::isUserCreated) + .filter(propertyDefinition -> !propertyDefinitionMap.containsKey(propertyDefinition.getName())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(userCreatedResourceProperties)) { + propertiesList.addAll(userCreatedResourceProperties); + } + } + } + + resource.setProperties(propertiesList); + } + } else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) { + throw new ByActionStatusComponentException( + componentsUtils.convertFromResultStatusEnum(properties.right().value(), JsonPresentationFields.PROPERTY)); + } + } + + private void addPropertyToList(final String resourceName, + final List propertiesList, + final Entry entry) { + final String propertyName = entry.getKey(); + if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(propertyName).matches()) { + log.debug("The property with invalid name {} occured upon import resource {}. ", propertyName, resourceName); + throw new ByActionStatusComponentException( + componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME, JsonPresentationFields.PROPERTY)); + } + final PropertyDefinition propertyDefinition = entry.getValue(); + propertyDefinition.setName(propertyName); + propertiesList.add(propertyDefinition); + } + + private void setAttributes(final Map originalToscaJsonMap, final Resource resource) { + final Map toscaJsonMap = new HashMap<>(originalToscaJsonMap); + ImportUtils.removeElementFromJsonMap(toscaJsonMap, "capabilities"); + final Either, ResultStatusEnum> getAttributeEither = ImportUtils.getAttributes(toscaJsonMap); + if (getAttributeEither.isRight()) { + final ResultStatusEnum resultStatus = getAttributeEither.right().value(); + if (resultStatus == ResultStatusEnum.ELEMENT_NOT_FOUND) { + return; + } + throw new ByActionStatusComponentException(componentsUtils.convertFromResultStatusEnum(resultStatus, JsonPresentationFields.ATTRIBUTES)); + } + final List attributeDefinitionList = new ArrayList<>(); + final Map attributeMap = getAttributeEither.left().value(); + if (MapUtils.isEmpty(attributeMap)) { + return; + } + for (final Entry entry : attributeMap.entrySet()) { + final String name = entry.getKey(); + if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) { + log.debug("Detected attribute with invalid name '{}' during resource '{}' import. ", name, resource.getName()); + throw new ByActionStatusComponentException( + componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_ATTRIBUTE_NAME, JsonPresentationFields.ATTRIBUTES)); + } + final AttributeDefinition attributeDefinition = entry.getValue(); + attributeDefinition.setName(name); + if (attributeDefinition.getEntry_schema() != null && attributeDefinition.getEntry_schema().getType() != null) { + attributeDefinition.setSchema(new SchemaDefinition()); + attributeDefinition.getSchema().setProperty(new PropertyDataDefinition()); + attributeDefinition.getSchema().getProperty().setType(entry.getValue().getEntry_schema().getType()); + } + attributeDefinitionList.add(attributeDefinition); + } + resource.setAttributes(attributeDefinitionList); + } + + private Resource setDerivedFrom(Map toscaJson, Resource resource) { + Either toscaDerivedFromElement = ImportUtils + .findFirstToscaStringElement(toscaJson, ToscaTagNamesEnum.DERIVED_FROM); + Resource derivedFromResource = null; + if (toscaDerivedFromElement.isLeft()) { + String derivedFrom = toscaDerivedFromElement.left().value(); + log.debug("Derived from TOSCA name is {}", derivedFrom); + resource.setDerivedFrom(Arrays.asList(new String[]{derivedFrom})); + Either latestByToscaResourceName = toscaOperationFacade.getLatestByToscaResourceName(derivedFrom, + resource.getModel()); + if (latestByToscaResourceName.isRight()) { + StorageOperationStatus operationStatus = latestByToscaResourceName.right().value(); + if (operationStatus == StorageOperationStatus.NOT_FOUND) { + operationStatus = StorageOperationStatus.PARENT_RESOURCE_NOT_FOUND; + } + log.debug("Error when fetching parent resource {}, error: {}", derivedFrom, operationStatus); + ActionStatus convertFromStorageResponse = componentsUtils.convertFromStorageResponse(operationStatus); + BeEcompErrorManager.getInstance().logBeComponentMissingError("Import TOSCA YAML", "resource", derivedFrom); + throw new ByActionStatusComponentException(convertFromStorageResponse, derivedFrom); + } + derivedFromResource = latestByToscaResourceName.left().value(); + } + return derivedFromResource; + } + + private void setCapabilities(Map toscaJson, Resource resource, + Resource parentResource) {// Note that parentResource can be null + Either, ResultStatusEnum> toscaCapabilities = ImportUtils + .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.CAPABILITIES); + if (toscaCapabilities.isLeft()) { + Map jsonCapabilities = toscaCapabilities.left().value(); + Map> moduleCapabilities = new HashMap<>(); + Iterator> capabilitiesNameValue = jsonCapabilities.entrySet().iterator(); + Set capNames = new HashSet<>(); + // Getting flattened list of capabilities of parent node - cap name + + // to cap type + Map capName2TypeMap = getCapName2Type(parentResource); + while (capabilitiesNameValue.hasNext()) { + Entry capabilityNameValue = capabilitiesNameValue.next(); + // Validating that no req/cap duplicates exist in imported YAML + String capNameLowerCase = capabilityNameValue.getKey().toLowerCase(); + if (capNames.contains(capNameLowerCase)) { + log.debug("More than one capability with same name {} (case-insensitive) in imported TOSCA file is invalid", capNameLowerCase); + throw new ByActionStatusComponentException(ActionStatus.IMPORT_DUPLICATE_REQ_CAP_NAME, "capability", capNameLowerCase); + } + capNames.add(capNameLowerCase); + CapabilityDefinition capabilityDef = createCapabilityFromImportFile(capabilityNameValue.getValue()); + capabilityDef.setName(capabilityNameValue.getKey()); + if (moduleCapabilities.containsKey(capabilityDef.getType())) { + moduleCapabilities.get(capabilityDef.getType()).add(capabilityDef); + } else { + List list = new ArrayList<>(); + list.add(capabilityDef); + moduleCapabilities.put(capabilityDef.getType(), list); + } + // Validating against req/cap of "derived from" node + Boolean validateVsParentCap = validateCapNameVsDerived(capName2TypeMap, capabilityDef.getType(), capabilityDef.getName()); + if (!validateVsParentCap) { + // Here parentResource is for sure not null, so it's + + // null-safe + + // Check added to avoid sonar warning + String parentResourceName = parentResource != null ? parentResource.getName() : ""; + log.debug("Capability with name {} already exists in parent {}", capabilityDef.getName(), parentResourceName); + throw new ByActionStatusComponentException(ActionStatus.IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED, "capability", + capabilityDef.getName().toLowerCase(), parentResourceName); + } + } + if (moduleCapabilities.size() > 0) { + resource.setCapabilities(moduleCapabilities); + } + } + } + + private Map getCapName2Type(Resource parentResource) { + Map capName2type = new HashMap<>(); + if (parentResource != null) { + Map> capabilities = parentResource.getCapabilities(); + if (capabilities != null) { + for (List capDefinitions : capabilities.values()) { + for (CapabilityDefinition capDefinition : capDefinitions) { + String nameLowerCase = capDefinition.getName().toLowerCase(); + if (capName2type.get(nameLowerCase) != null) { + String parentResourceName = parentResource.getName(); + log.debug("Resource with name {} has more than one capability with name {}, ignoring case", parentResourceName, + nameLowerCase); + BeEcompErrorManager.getInstance().logInternalDataError("Import resource", + "Parent resource " + parentResourceName + " of imported resource has one or more capabilities with name " + + nameLowerCase, ErrorSeverity.ERROR); + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + capName2type.put(nameLowerCase, capDefinition.getType()); + } + } + } + } + return capName2type; + } + + private Map getReqName2Type(Resource parentResource) { + Map reqName2type = new HashMap<>(); + if (parentResource != null) { + Map> requirements = parentResource.getRequirements(); + if (requirements != null) { + for (List reqDefinitions : requirements.values()) { + for (RequirementDefinition reqDefinition : reqDefinitions) { + String nameLowerCase = reqDefinition.getName().toLowerCase(); + if (reqName2type.get(nameLowerCase) != null) { + String parentResourceName = parentResource.getName(); + log.debug("Resource with name {} has more than one requirement with name {}, ignoring case", parentResourceName, + nameLowerCase); + BeEcompErrorManager.getInstance().logInternalDataError("Import resource", + "Parent resource " + parentResourceName + " of imported resource has one or more requirements with name " + + nameLowerCase, ErrorSeverity.ERROR); + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + reqName2type.put(nameLowerCase, reqDefinition.getCapability()); + } + } + } + } + return reqName2type; + } + + private Boolean validateCapNameVsDerived(Map parentCapName2Type, String childCapabilityType, String reqCapName) { + String capNameLowerCase = reqCapName.toLowerCase(); + log.trace("Validating capability {} vs parent resource", capNameLowerCase); + String parentCapType = parentCapName2Type.get(capNameLowerCase); + if (parentCapType != null) { + if (childCapabilityType.equals(parentCapType)) { + log.debug("Capability with name {} is of same type {} for imported resource and its parent - this is OK", capNameLowerCase, + childCapabilityType); + return true; + } + Either capabilityTypeDerivedFrom = capabilityTypeOperation + .isCapabilityTypeDerivedFrom(childCapabilityType, parentCapType); + if (capabilityTypeDerivedFrom.isRight()) { + log.debug("Couldn't check whether imported resource capability derives from its parent's capability"); + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(capabilityTypeDerivedFrom.right().value())); + } + return capabilityTypeDerivedFrom.left().value(); + } + return true; + } + + private CapabilityDefinition createCapabilityFromImportFile(Object capabilityJson) { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + if (capabilityJson instanceof String) { + String capabilityJsonString = (String) capabilityJson; + capabilityDefinition.setType(capabilityJsonString); + } else if (capabilityJson instanceof Map) { + Map capabilityJsonMap = (Map) capabilityJson; + // Type + if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) { + capabilityDefinition.setType((String) capabilityJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName())); + } + // ValidSourceTypes + if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) { + capabilityDefinition + .setValidSourceTypes((List) capabilityJsonMap.get(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())); + } + // ValidSourceTypes + if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.DESCRIPTION.getElementName())) { + capabilityDefinition.setDescription((String) capabilityJsonMap.get(ToscaTagNamesEnum.DESCRIPTION.getElementName())); + } + if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) { + List occurrencesList = (List) capabilityJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName()); + validateOccurrences(occurrencesList); + capabilityDefinition.setMinOccurrences(occurrencesList.get(0).toString()); + capabilityDefinition.setMaxOccurrences(occurrencesList.get(1).toString()); + } + if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.PROPERTIES.getElementName())) { + Either, ResultStatusEnum> propertiesRes = ImportUtils.getProperties(capabilityJsonMap); + if (propertiesRes.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND); + } else { + propertiesRes.left().value().entrySet().stream().forEach(e -> e.getValue().setName(e.getKey().toLowerCase())); + List capabilityProperties = propertiesRes.left().value().values().stream() + .map(p -> new ComponentInstanceProperty(p, p.getDefaultValue(), null)).collect(Collectors.toList()); + capabilityDefinition.setProperties(capabilityProperties); + } + } + } else if (!(capabilityJson instanceof List)) { + throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML); + } + return capabilityDefinition; + } + + private void handleImportResourceException(UploadResourceInfo resourceMetaData, User user, boolean isNormative, RuntimeException e) { + ResponseFormat responseFormat; + ComponentException newException; + if (e instanceof ComponentException) { + ComponentException componentException = (ComponentException) e; + responseFormat = componentException.getResponseFormat(); + if (responseFormat == null) { + responseFormat = getResponseFormatManager().getResponseFormat(componentException.getActionStatus(), componentException.getParams()); + } + newException = componentException; + } else { + responseFormat = getResponseFormatManager().getResponseFormat(ActionStatus.GENERAL_ERROR); + newException = new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + String payloadName = (resourceMetaData != null) ? resourceMetaData.getPayloadName() : ""; + BeEcompErrorManager.getInstance().logBeSystemError("Import Resource " + payloadName); + log.debug("Error when importing resource from payload:{} Exception text: {}", payloadName, e.getMessage(), e); + auditErrorImport(resourceMetaData, user, responseFormat, isNormative); + throw newException; + } + + private void auditErrorImport(UploadResourceInfo resourceMetaData, User user, ResponseFormat errorResponseWrapper, boolean isNormative) { + String version, lifeCycleState; + if (isNormative) { + version = TypeUtils.getFirstCertifiedVersionVersion(); + lifeCycleState = LifecycleStateEnum.CERTIFIED.name(); + } else { + version = ""; + lifeCycleState = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name(); + } + String message = ""; + if (errorResponseWrapper.getMessageId() != null) { + message = errorResponseWrapper.getMessageId() + ": "; + } + message += errorResponseWrapper.getFormattedMessage(); + AuditEventFactory factory = new AuditImportResourceAdminEventFactory( + CommonAuditData.newBuilder().status(errorResponseWrapper.getStatus()).description(message).requestId(ThreadLocalsHolder.getUuid()) + .build(), new ResourceCommonInfo(resourceMetaData.getName(), ComponentTypeEnum.RESOURCE.getValue()), + ResourceVersionInfo.newBuilder().state(lifeCycleState).version(version).build(), + ResourceVersionInfo.newBuilder().state("").version("").build(), "", user, ""); + getAuditingManager().auditEvent(factory); + } + + private void setResourceMetaData(Resource resource, String resourceYml, UploadResourceInfo resourceMetaData) { + Map ymlObj = new Yaml().load(resourceYml); + String toscaName = getToscaResourceName(ymlObj); + final Either latestByToscaName = toscaOperationFacade + .getLatestByToscaResourceName(toscaName, resourceMetaData.getModel()); + if (latestByToscaName.isLeft() && resourceMetaData instanceof DefaultUploadResourceInfo) { + setMetaDataFromLatestResource(resource, latestByToscaName.left().value()); + } else { + setMetaDataFromJson(resourceMetaData, resource); + } + } + + private void setMetaDataFromJson(final UploadResourceInfo resourceMetaData, final Resource resource) { + this.populateResourceMetadata(resourceMetaData, resource); + resource.setCreatorUserId(resourceMetaData.getContactId()); + final String payloadData = resourceMetaData.getPayloadData(); + if (payloadData != null) { + resource.setToscaVersion(getToscaVersion(payloadData)); + } + final List categories = resourceMetaData.getCategories(); + calculateResourceIsAbstract(resource, categories); + } + + private void setMetaDataFromLatestResource(Resource resource, Resource latestResource) { + if (resource != null && latestResource != null) { + resource.setCreatorUserId(latestResource.getContactId()); + resource.setDescription(latestResource.getDescription()); + resource.setTags(latestResource.getTags()); + resource.setCategories(latestResource.getCategories()); + resource.setContactId(latestResource.getContactId()); + resource.setName(latestResource.getName()); + resource.setIcon(latestResource.getIcon()); + resource.setResourceVendorModelNumber(latestResource.getResourceVendorModelNumber()); + resource.setResourceType(latestResource.getResourceType()); + if (latestResource.getVendorName() != null) { + resource.setVendorName(latestResource.getVendorName()); + } + if (latestResource.getVendorRelease() != null) { + resource.setVendorRelease(latestResource.getVendorRelease()); + } + if (latestResource.getModel() != null) { + resource.setModel(latestResource.getModel()); + } + if (latestResource.getToscaVersion() != null) { + resource.setToscaVersion(latestResource.getToscaVersion()); + } + final List categories = latestResource.getCategories(); + calculateResourceIsAbstract(resource, categories); + } + } + + private Map decodePayload(final String payloadData) { + final String decodedPayload = new String(Base64.decodeBase64(payloadData)); + return (Map) new Yaml().load(decodedPayload); + } + + private String getToscaVersion(final String payloadData) { + final Map mappedToscaTemplate = decodePayload(payloadData); + final Either findFirstToscaStringElement = ImportUtils + .findFirstToscaStringElement(mappedToscaTemplate, ToscaTagNamesEnum.TOSCA_VERSION); + if (findFirstToscaStringElement.isLeft()) { + return findFirstToscaStringElement.left().value(); + } else { + return null; + } + } + + private void calculateResourceIsAbstract(Resource resource, List categories) { + if (categories != null && !categories.isEmpty()) { + CategoryDefinition categoryDef = categories.get(0); + resource.setAbstract(false); + if (categoryDef != null && categoryDef.getName() != null && categoryDef.getName().equals(Constants.ABSTRACT_CATEGORY_NAME)) { + SubCategoryDefinition subCategoryDef = categoryDef.getSubcategories().get(0); + if (subCategoryDef != null && subCategoryDef.getName().equals(Constants.ABSTRACT_SUBCATEGORY)) { + resource.setAbstract(true); + } + } + } + } + + private void setConstantMetaData(Resource resource, boolean shouldBeCertified) { + String version; + LifecycleStateEnum state; + if (shouldBeCertified) { + version = TypeUtils.getFirstCertifiedVersionVersion(); + state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE; + } else { + version = ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION; + state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT; + } + resource.setVersion(version); + resource.setLifecycleState(state); + resource.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION); + resource.setVendorName(ImportUtils.Constants.VENDOR_NAME); + resource.setVendorRelease(ImportUtils.Constants.VENDOR_RELEASE); + } + + private void validateOccurrences(List occurrensesList) { + if (!ValidationUtils.validateListNotEmpty(occurrensesList)) { + log.debug("Occurrenses list empty"); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + if (occurrensesList.size() < 2) { + log.debug("Occurrenses list size not 2"); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + Object minObj = occurrensesList.get(0); + Object maxObj = occurrensesList.get(1); + Integer minOccurrences; + Integer maxOccurrences; + if (minObj instanceof Integer) { + minOccurrences = (Integer) minObj; + } else { + log.debug("Invalid occurrenses format. low_bound occurrense must be Integer {}", minObj); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + if (minOccurrences < 0) { + log.debug("Invalid occurrenses format.low_bound occurrense negative {}", minOccurrences); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + if (maxObj instanceof String) { + if (!"UNBOUNDED".equals(maxObj)) { + log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + } else { + if (maxObj instanceof Integer) { + maxOccurrences = (Integer) maxObj; + } else { + log.debug("Invalid occurrenses format. Max occurrence is {}", maxObj); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + if (maxOccurrences < 0 || maxOccurrences < minOccurrences) { + log.debug("Invalid occurrenses format. min occurrence is {}, Max occurrence is {}", minOccurrences, maxOccurrences); + throw new ByActionStatusComponentException(ActionStatus.INVALID_OCCURRENCES); + } + } + } + + public synchronized void init(ServletContext servletContext) { + if (this.servletContext == null) { + this.servletContext = servletContext; + responseFormatManager = ResponseFormatManager.getInstance(); + resourceBusinessLogic = getResourceBL(servletContext); + } + } + + public boolean isResourceExist(String resourceName) { + return resourceBusinessLogic.isResourceExist(resourceName); + } + + private ResourceBusinessLogic getResourceBL(ServletContext context) { + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context + .getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + return webApplicationContext.getBean(ResourceBusinessLogic.class); + } + + public ServletContext getServletContext() { + return servletContext; + } + + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + + public AuditingManager getAuditingManager() { + return auditingManager; + } + + @Autowired + public void setAuditingManager(AuditingManager auditingManager) { + this.auditingManager = auditingManager; + } + + public ResponseFormatManager getResponseFormatManager() { + return responseFormatManager; + } + + public void setResponseFormatManager(ResponseFormatManager responseFormatManager) { + this.responseFormatManager = responseFormatManager; + } + + public ResourceBusinessLogic getResourceBusinessLogic() { + return resourceBusinessLogic; + } + + @Autowired + public void setResourceBusinessLogic(ResourceBusinessLogic resourceBusinessLogic) { + this.resourceBusinessLogic = resourceBusinessLogic; + } + + public IGraphLockOperation getGraphLockOperation() { + return graphLockOperation; + } + + @Autowired + public void setGraphLockOperation(IGraphLockOperation graphLockOperation) { + this.graphLockOperation = graphLockOperation; + } + + private List extractDataTypeFromJson(final ResourceBusinessLogic resourceBusinessLogic, + final Map foundElements, + final String model) { + final List dataTypeDefinitionList = new ArrayList<>(); + if (MapUtils.isNotEmpty(foundElements)) { + final Either, JanusGraphOperationStatus> dataTypeCacheAll = + resourceBusinessLogic.applicationDataTypeCache.getAll(model); + if (dataTypeCacheAll.isLeft()) { + for (final Entry attributeNameValue : foundElements.entrySet()) { + final Object value = attributeNameValue.getValue(); + if (value instanceof Map) { + final DataTypeDefinition dataTypeDefinition = createDataTypeDefinitionWithName(attributeNameValue); + final DataTypeDefinition dataTypeDefinitionParent = dataTypeCacheAll.left().value() + .get(dataTypeDefinition.getDerivedFromName()); + dataTypeDefinition.setDerivedFrom(dataTypeDefinitionParent); + dataTypeDefinitionList.add(dataTypeDefinition); + } else { + dataTypeDefinitionList.add(createDataType(String.valueOf(value))); + } + } + } + } + return dataTypeDefinitionList; + } }