diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java index 5511935f918..d22f4eac7cc 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java @@ -27,10 +27,13 @@ import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.discovery.AtlasSearchResult; import org.apache.atlas.model.discovery.SearchParameters; +import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef; import org.apache.atlas.model.typedef.AtlasStructDef; import org.apache.atlas.repository.Constants; +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.type.AtlasBusinessMetadataType; import org.apache.atlas.type.AtlasStructType; @@ -58,6 +61,9 @@ public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2 attributeDefs = businessMetadataDef.getAttributeDefs(); + if (businessMetadataDef == null || CollectionUtils.isEmpty(businessMetadataDef.getAttributeDefs())) { + return; + } - for (AtlasStructDef.AtlasAttributeDef attributeDef : attributeDefs) { - String qualifiedName = AtlasStructType.AtlasAttribute.getQualifiedAttributeName(businessMetadataDef, attributeDef.getName()); - String vertexPropertyName = AtlasStructType.AtlasAttribute.generateVertexPropertyName(businessMetadataDef, attributeDef, qualifiedName); - Set applicableTypes = AtlasJson.fromJson(attributeDef.getOption(AtlasBusinessMetadataDef.ATTR_OPTION_APPLICABLE_ENTITY_TYPES), Set.class); + for (AtlasStructDef.AtlasAttributeDef attributeDef : businessMetadataDef.getAttributeDefs()) { + validateAttributeReferences(businessMetadataDef, attributeDef); + } + } - if (CollectionUtils.isNotEmpty(applicableTypes) && isBusinessAttributePresent(vertexPropertyName, applicableTypes)) { - throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, typeName); - } - } + private void validateAttributeReferences(AtlasBusinessMetadataDef bmDef, AtlasStructDef.AtlasAttributeDef attributeDef) throws AtlasBaseException { + String applicableTypesStr = attributeDef.getOption(ATTR_OPTION_APPLICABLE_ENTITY_TYPES); + Set applicableTypes = StringUtils.isBlank(applicableTypesStr) ? null : AtlasJson.fromJson(applicableTypesStr, Set.class); + + if (CollectionUtils.isEmpty(applicableTypes)) { + return; + } + + String qualifiedName = AtlasStructType.AtlasAttribute.getQualifiedAttributeName(bmDef, attributeDef.getName()); + String vertexPropertyName = AtlasStructType.AtlasAttribute.generateVertexPropertyName(bmDef, attributeDef, qualifiedName); + + boolean isPresent; + long startTime = System.currentTimeMillis(); + + if (Boolean.TRUE.equals(attributeDef.getIsIndexable())) { + isPresent = isBusinessAttributePresent(vertexPropertyName, applicableTypes); + } else { + isPresent = isBusinessAttributePresentInGraph(vertexPropertyName, applicableTypes); + } + + if (LOG.isDebugEnabled()) { + LOG.info("Reference check for attribute {} took {} ms. Found: {}", + attributeDef.getName(), (System.currentTimeMillis() - startTime), isPresent); + } + + if (isPresent) { + throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, bmDef.getName()); } } private boolean isBusinessAttributePresent(String attrName, Set applicableTypes) throws AtlasBaseException { SearchParameters.FilterCriteria criteria = new SearchParameters.FilterCriteria(); - criteria.setAttributeName(attrName); - criteria.setOperator(SearchParameters.Operator.NOT_EMPTY); + criteria.setOperator(SearchParameters.Operator.NOT_NULL); SearchParameters.FilterCriteria entityFilters = new SearchParameters.FilterCriteria(); - entityFilters.setCondition(SearchParameters.FilterCriteria.Condition.OR); entityFilters.setCriterion(Collections.singletonList(criteria)); SearchParameters searchParameters = new SearchParameters(); - searchParameters.setTypeName(String.join(SearchContext.TYPENAME_DELIMITER, applicableTypes)); searchParameters.setExcludeDeletedEntities(true); searchParameters.setIncludeSubClassifications(false); searchParameters.setEntityFilters(entityFilters); - searchParameters.setAttributes(Collections.singleton(attrName)); - searchParameters.setOffset(0); + searchParameters.setAttributes(Collections.emptySet()); searchParameters.setLimit(1); AtlasSearchResult atlasSearchResult = entityDiscoveryService.searchWithParameters(searchParameters); + return atlasSearchResult != null && CollectionUtils.isNotEmpty(atlasSearchResult.getEntities()); + } + + private boolean isBusinessAttributePresentInGraph(String vertexPropertyName, Set applicableTypes) { + if (graph == null || CollectionUtils.isEmpty(applicableTypes)) { + return false; + } + + try { + for (String typeName : applicableTypes) { - return CollectionUtils.isNotEmpty(atlasSearchResult.getEntities()); + Iterable vertices = graph.query() + .has(Constants.ENTITY_TYPE_PROPERTY_KEY, typeName) + .has(vertexPropertyName, AtlasGraphQuery.ComparisionOperator.NOT_EQUAL, (Object) null) + .has(Constants.STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE.name()) + .vertices(); + + if (vertices != null && vertices.iterator().hasNext()) { + if (LOG.isDebugEnabled()) { + LOG.info("Found at least one reference for {} on type {}", vertexPropertyName, typeName); + } + return true; + } + } + } catch (Exception e) { + LOG.error("Error occurred while querying graph for references of property: {}", vertexPropertyName, e); + return true; + } + return false; } }