/* * Copyright © 2016-2017 European Support Limited * * 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. */ package org.openecomp.sdc.validation.impl.validators; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import org.openecomp.core.validation.types.GlobalValidationContext; import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; import org.openecomp.sdc.heat.datatypes.model.Output; import org.openecomp.sdc.heat.datatypes.model.Resource; import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions; import org.openecomp.sdc.heat.services.HeatStructureUtil; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; import org.openecomp.sdc.validation.ValidationContext; import org.openecomp.sdc.validation.base.ResourceBaseValidator; import org.openecomp.sdc.validation.type.ConfigConstants; import org.openecomp.sdc.validation.type.HeatResourceValidationContext; public class HeatResourceValidator extends ResourceBaseValidator { private static final Logger LOGGER = LoggerFactory.getLogger(ResourceBaseValidator.class); private static final String GET_ATTR = "get_attr"; @Override public void init(Map properties) { super.init((Map) properties.get(ConfigConstants.Resource_Base_Validator)); } @Override public ValidationContext createValidationContext(String fileName, String envFileName, HeatOrchestrationTemplate heatOrchestrationTemplate, GlobalValidationContext globalContext) { Map resourcesMap = heatOrchestrationTemplate.getResources() == null ? new HashMap<>() : heatOrchestrationTemplate.getResources(); Map outputMap = heatOrchestrationTemplate.getOutputs() == null ? new HashMap<>() : heatOrchestrationTemplate.getOutputs(); Map>>> typeToPointingResourcesMap = new HashMap<>(); initTypeRelationsMap(fileName, resourcesMap, outputMap, typeToPointingResourcesMap, globalContext); return new HeatResourceValidationContext(heatOrchestrationTemplate, typeToPointingResourcesMap, envFileName); } private void initTypeRelationsMap(String fileName, Map resourceMap, Map outputMap, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { initTypeRelationsMapFromResourcesMap(fileName, resourceMap, typeToPointingResourcesMap, globalContext); initTypeRelationsMapFromOutputsMap(fileName, resourceMap, outputMap, typeToPointingResourcesMap, globalContext); } private void initTypeRelationsMapFromOutputsMap(String fileName, Map resourceMap, Map outputMap, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { for (Map.Entry outputEntry : outputMap.entrySet()) { Object outputValue = outputEntry.getValue().getValue(); Set referencedResources = HeatStructureUtil .getReferencedValuesByFunctionName(fileName, ResourceReferenceFunctions.GET_RESOURCE.getFunction(), outputValue, globalContext); updateRelationsMapWithOutputsReferences(outputEntry, resourceMap, referencedResources, typeToPointingResourcesMap); } } private void updateRelationsMapWithOutputsReferences(Map.Entry outputEntry, Map resourceMap, Set referencedResources, Map>>> typeToPointingResourcesMap) { for (String pointedResourceName : referencedResources) { Resource pointedResource = resourceMap.get(pointedResourceName); if (Objects.nonNull(pointedResource)) { initCurrentResourceTypeInMap(pointedResourceName, pointedResource.getType(), "output", typeToPointingResourcesMap); typeToPointingResourcesMap.get(pointedResource.getType()).get(pointedResourceName).get("output").add(outputEntry.getKey()); } } } private void initTypeRelationsMapFromResourcesMap(String fileName, Map resourceMap, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { for (Map.Entry resourceEntry : resourceMap.entrySet()) { Resource pointingResource = resourceEntry.getValue(); Map properties = pointingResource.getProperties() == null ? new HashMap<>() : pointingResource.getProperties(); Set referencedResourcesByGetResource = getResourcesIdsPointedByCurrentResource(fileName, ResourceReferenceFunctions.GET_RESOURCE, properties, globalContext); Set referencedResourcesByGetAttr = handleGetAttrBetweenResources(properties); referencedResourcesByGetResource.addAll(referencedResourcesByGetAttr); updateRelationsMapWithCurrentResourceReferences(resourceMap, resourceEntry, referencedResourcesByGetResource, typeToPointingResourcesMap); } } private void updateRelationsMapWithCurrentResourceReferences(Map resourceMap, Map.Entry currentResourceEntry, Set referencedResourcesFromCurrentResource, Map>>> typeToPointingResourcesMap) { for (String pointedResourceName : referencedResourcesFromCurrentResource) { Resource pointedResource = resourceMap.get(pointedResourceName); if (Objects.nonNull(pointedResource)) { String pointedResourceType = pointedResource.getType(); updateMapWithRelationsBetweenResources(pointedResourceName, pointedResourceType, currentResourceEntry, typeToPointingResourcesMap); } } } private void updateMapWithRelationsBetweenResources(String pointedResourceName, String pointedResourceType, Map.Entry currentResourceEntry, Map>>> typeToPointingResourcesMap) { initCurrentResourceTypeInMap(pointedResourceName, pointedResourceType, currentResourceEntry.getValue().getType(), typeToPointingResourcesMap); typeToPointingResourcesMap.get(pointedResourceType).get(pointedResourceName).get(currentResourceEntry.getValue().getType()) .add(currentResourceEntry.getKey()); } private void initCurrentResourceTypeInMap(String resourceName, String resourceType, String pointingResourceType, Map>>> typeToPointingResourcesMap) { typeToPointingResourcesMap.putIfAbsent(resourceType, new HashMap<>()); typeToPointingResourcesMap.get(resourceType).putIfAbsent(resourceName, new HashMap<>()); typeToPointingResourcesMap.get(resourceType).get(resourceName).putIfAbsent(pointingResourceType, new ArrayList<>()); } private Set handleGetAttrBetweenResources(Map properties) { Set referencedResourcesByGetAttr = new HashSet<>(); for (Map.Entry proprtyEntry : properties.entrySet()) { referencedResourcesByGetAttr.addAll(getGetAttrReferencesInCaseOfContrail(proprtyEntry.getValue())); } return referencedResourcesByGetAttr; } private Set getGetAttrReferencesInCaseOfContrail(Object propertyValue) { Set getAttrReferences = new HashSet<>(); if (propertyValue instanceof Map) { if (((Map) propertyValue).containsKey(GET_ATTR)) { if (validatePropertyValueAndAddAttrReferencesInSet(propertyValue, getAttrReferences)) { return getAttrReferences; } } else { Collection valCollection = ((Map) propertyValue).values(); for (Object entryValue : valCollection) { getAttrReferences.addAll(getGetAttrReferencesInCaseOfContrail(entryValue)); } } } else if (propertyValue instanceof List) { for (Object prop : (List) propertyValue) { getAttrReferences.addAll(getGetAttrReferencesInCaseOfContrail(prop)); } } return getAttrReferences; } private boolean validatePropertyValueAndAddAttrReferencesInSet(Object propertyValue, Set getAttrReferences) { Object value = ((Map) propertyValue).get(GET_ATTR); if (value instanceof List && ((List) value).size() == 2 && ("fq_name").equals(((List) value).get(1))) { if (((List) value).get(0) instanceof String) { String attrReference = (((List) value).get(0)).toString(); getAttrReferences.add(attrReference); return true; } else { LOGGER.warn("invalid format of 'get_attr' function - " + propertyValue.toString()); } } return false; } private Set getResourcesIdsPointedByCurrentResource(String fileName, ResourceReferenceFunctions function, Map properties, GlobalValidationContext globalContext) { Set referencedResources = new HashSet<>(); for (Map.Entry propertyEntry : properties.entrySet()) { referencedResources.addAll( HeatStructureUtil.getReferencedValuesByFunctionName(fileName, function.getFunction(), propertyEntry.getValue(), globalContext)); } return referencedResources; } }