This is an automated email from the ASF dual-hosted git repository. pinal pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/branch-2.0 by this push: new 6247e34 ATLAS-4124 Restrict user from deleting Business Metadata, if Business Metadata is already associated with an entity 6247e34 is described below commit 6247e34128c70db879ed75e8c79f65eba1cc1201 Author: Mandar Ambawane <mandar.ambaw...@freestoneinfotech.com> AuthorDate: Mon Apr 12 21:22:56 2021 +0530 ATLAS-4124 Restrict user from deleting Business Metadata, if Business Metadata is already associated with an entity Signed-off-by: Pinal <pinal-shah> --- .../atlas/model/discovery/SearchParameters.java | 3 +- .../test/java/org/apache/atlas/TestUtilsV2.java | 8 +- .../apache/atlas/discovery/SearchProcessor.java | 3 + .../graph/v2/AtlasBusinessMetadataDefStoreV2.java | 56 ++++- .../store/graph/v2/AtlasTypeDefGraphStoreV2.java | 9 +- .../atlas/web/adapters/TypeDefsRESTTest.java | 279 +++++++++++++++++++++ 6 files changed, 353 insertions(+), 5 deletions(-) diff --git a/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java b/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java index 367c5b8..9d2cd4f 100644 --- a/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java +++ b/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java @@ -464,7 +464,8 @@ public class SearchParameters implements Serializable { CONTAINS_ALL(new String[]{"containsAll", "CONTAINSALL", "contains_all", "CONTAINS_ALL"}), IS_NULL(new String[]{"isNull", "ISNULL", "is_null", "IS_NULL"}), NOT_NULL(new String[]{"notNull", "NOTNULL", "not_null", "NOT_NULL"}), - TIME_RANGE(new String[]{"timerange", "TIMERANGE","time_range","TIME_RANGE"}) + TIME_RANGE(new String[]{"timerange", "TIMERANGE","time_range","TIME_RANGE"}), + NOT_EMPTY(new String[]{"notEmpty", "NOTEMPTY", "not_empty", "NOT_EMPTY"}) ; static final Map<String, Operator> operatorsMap = new HashMap<>(); diff --git a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java index 80ab6b4..d9e2d19 100755 --- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java +++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java @@ -740,10 +740,16 @@ public final class TestUtilsV2 { createOptionalAttrDef("attr19", "array<date>", options, _description), createOptionalAttrDef("attr20", "array<ENUM_1>", options, _description)); + options.put("applicableEntityTypes", "[\"" + SUPER_TYPE_NAME + "\"]"); + + AtlasBusinessMetadataDef bmWithSuperType = createBusinessMetadataDef("bmWithSuperType", _description,"1.0", + createOptionalAttrDef("attrSuperBoolean", AtlasBusinessMetadataDef.ATLAS_TYPE_BOOLEAN, options, _description ), + createOptionalAttrDef("attrSuperString", AtlasBusinessMetadataDef.ATLAS_TYPE_STRING, options, _description )); + AtlasTypesDef ret = AtlasTypeUtil.getTypesDef(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), - Arrays.asList(bmNoApplicableTypes, bmNoAttributes, bmWithAllTypes, bmWithAllTypesMV)); + Arrays.asList(bmNoApplicableTypes, bmNoAttributes, bmWithAllTypes, bmWithAllTypesMV, bmWithSuperType)); populateSystemAttributes(ret); diff --git a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java index 275fc78..3750799 100644 --- a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java +++ b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java @@ -126,6 +126,9 @@ public abstract class SearchProcessor { OPERATOR_MAP.put(SearchParameters.Operator.NOT_NULL, INDEX_SEARCH_PREFIX + "\"%s\":[* TO *]"); OPERATOR_PREDICATE_MAP.put(SearchParameters.Operator.NOT_NULL, getNotNullPredicateGenerator()); + OPERATOR_MAP.put(SearchParameters.Operator.NOT_EMPTY, INDEX_SEARCH_PREFIX + "\"%s\":[* TO *]"); + OPERATOR_PREDICATE_MAP.put(SearchParameters.Operator.NOT_EMPTY, getNotEmptyPredicateGenerator()); + OPERATOR_MAP.put(SearchParameters.Operator.TIME_RANGE, INDEX_SEARCH_PREFIX + "\"%s\": [%s TO %s]"); OPERATOR_PREDICATE_MAP.put(SearchParameters.Operator.TIME_RANGE, getInRangePredicateGenerator()); } 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 d0d54af..ece1a23 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 @@ -21,8 +21,12 @@ import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.authorize.AtlasAuthorizationUtils; import org.apache.atlas.authorize.AtlasPrivilege; import org.apache.atlas.authorize.AtlasTypeAccessRequest; +import org.apache.atlas.discovery.EntityDiscoveryService; +import org.apache.atlas.discovery.SearchContext; import org.apache.atlas.exception.AtlasBaseException; 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.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef; import org.apache.atlas.model.typedef.AtlasStructDef; @@ -33,6 +37,7 @@ import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.typesystem.types.DataTypes; +import org.apache.atlas.utils.AtlasJson; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -40,6 +45,7 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -49,9 +55,12 @@ import static org.apache.atlas.model.typedef.AtlasBusinessMetadataDef.ATTR_OPTIO public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2<AtlasBusinessMetadataDef> { private static final Logger LOG = LoggerFactory.getLogger(AtlasBusinessMetadataDefStoreV2.class); + private final EntityDiscoveryService entityDiscoveryService; + @Inject - public AtlasBusinessMetadataDefStoreV2(AtlasTypeDefGraphStoreV2 typeDefStore, AtlasTypeRegistry typeRegistry) { + public AtlasBusinessMetadataDefStoreV2(AtlasTypeDefGraphStoreV2 typeDefStore, AtlasTypeRegistry typeRegistry, EntityDiscoveryService entityDiscoveryService) { super(typeDefStore, typeRegistry); + this.entityDiscoveryService = entityDiscoveryService; } @Override @@ -305,6 +314,8 @@ public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2<Atl throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } + checkBusinessMetadataRef(existingDef.getName()); + if (LOG.isDebugEnabled()) { LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByName({}): {}", name, ret); } @@ -327,6 +338,8 @@ public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2<Atl throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); } + checkBusinessMetadataRef(existingDef.getName()); + if (LOG.isDebugEnabled()) { LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByGuid({}): ret={}", guid, ret); } @@ -380,4 +393,45 @@ public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2<Atl return ret; } + + private void checkBusinessMetadataRef(String typeName) throws AtlasBaseException { + AtlasBusinessMetadataDef businessMetadataDef = typeRegistry.getBusinessMetadataDefByName(typeName); + if (businessMetadataDef != null) { + List<AtlasStructDef.AtlasAttributeDef> attributeDefs = businessMetadataDef.getAttributeDefs(); + + for (AtlasStructDef.AtlasAttributeDef attributeDef : attributeDefs) { + String qualifiedName = AtlasStructType.AtlasAttribute.getQualifiedAttributeName(businessMetadataDef, attributeDef.getName()); + String vertexPropertyName = AtlasStructType.AtlasAttribute.generateVertexPropertyName(businessMetadataDef, attributeDef, qualifiedName); + Set<String> applicableTypes = AtlasJson.fromJson(attributeDef.getOption(AtlasBusinessMetadataDef.ATTR_OPTION_APPLICABLE_ENTITY_TYPES), Set.class); + + if (isBusinessAttributePresent(vertexPropertyName, applicableTypes)) { + throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, typeName); + } + } + } + } + + private boolean isBusinessAttributePresent(String attrName, Set<String> applicableTypes) throws AtlasBaseException { + SearchParameters.FilterCriteria criteria = new SearchParameters.FilterCriteria(); + criteria.setAttributeName(attrName); + criteria.setOperator(SearchParameters.Operator.NOT_EMPTY); + + 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.setLimit(1); + + AtlasSearchResult atlasSearchResult = entityDiscoveryService.searchWithParameters(searchParameters); + + return CollectionUtils.isNotEmpty(atlasSearchResult.getEntities()); + } + } diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java index 96fb3b4..b9d41bb 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java @@ -22,6 +22,7 @@ import com.google.common.base.Preconditions; import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.RequestContext; import org.apache.atlas.annotation.GraphTransaction; +import org.apache.atlas.discovery.EntityDiscoveryService; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.listener.TypeDefChangeListener; import org.apache.atlas.model.typedef.*; @@ -65,12 +66,16 @@ public class AtlasTypeDefGraphStoreV2 extends AtlasTypeDefGraphStore { protected final AtlasGraph atlasGraph; + private EntityDiscoveryService entityDiscoveryService; + @Inject public AtlasTypeDefGraphStoreV2(AtlasTypeRegistry typeRegistry, Set<TypeDefChangeListener> typeDefChangeListeners, - AtlasGraph atlasGraph) { + AtlasGraph atlasGraph, + EntityDiscoveryService entityDiscoveryService) { super(typeRegistry, typeDefChangeListeners); this.atlasGraph = atlasGraph; + this.entityDiscoveryService = entityDiscoveryService; LOG.debug("<== AtlasTypeDefGraphStoreV1()"); } @@ -102,7 +107,7 @@ public class AtlasTypeDefGraphStoreV2 extends AtlasTypeDefGraphStore { @Override protected AtlasDefStore<AtlasBusinessMetadataDef> getBusinessMetadataDefStore(AtlasTypeRegistry typeRegistry) { - return new AtlasBusinessMetadataDefStoreV2(this, typeRegistry); + return new AtlasBusinessMetadataDefStoreV2(this, typeRegistry, this.entityDiscoveryService); } @Override diff --git a/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java b/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java new file mode 100644 index 0000000..962345b --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java @@ -0,0 +1,279 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.apache.atlas.web.adapters; + +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.RequestContext; +import org.apache.atlas.TestModules; +import org.apache.atlas.TestUtilsV2; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.EntityMutationResponse; +import org.apache.atlas.model.instance.EntityMutations; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef; +import org.apache.atlas.model.typedef.AtlasTypesDef; +import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.web.rest.EntityREST; +import org.apache.atlas.web.rest.TypesREST; +import org.apache.commons.lang.time.DateUtils; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import java.util.*; + +@Guice(modules = {TestModules.TestOnlyModule.class}) +public class TypeDefsRESTTest { + @Inject + private TypesREST typesREST; + + @Inject + EntityREST entityREST; + + @Inject + private AtlasTypeDefStore typeStore; + + private AtlasEntity dbEntity; + + private String bmWithAllTypes; + private String bmWithSuperType; + private String bmWithAllTypesMV; + + @BeforeClass + public void setUp() throws Exception { + AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes(); + typeStore.createTypesDef(typesDef); + AtlasTypesDef enumDef = TestUtilsV2.defineEnumTypes(); + typeStore.createTypesDef(enumDef); + AtlasTypesDef metadataDef = TestUtilsV2.defineBusinessMetadataTypes(); + typeStore.createTypesDef(metadataDef); + bmWithAllTypes = "bmWithAllTypes"; + bmWithSuperType = "bmWithSuperType"; + bmWithAllTypesMV = "bmWithAllTypesMV"; + } + + @AfterMethod + public void cleanup() throws Exception { + RequestContext.clear(); + } + + private void createTestEntity() throws AtlasBaseException { + AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); + + final EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntity.AtlasEntitiesWithExtInfo(dbEntity)); + + Assert.assertNotNull(response); + List<AtlasEntityHeader> entitiesMutated = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); + + Assert.assertNotNull(entitiesMutated); + Assert.assertEquals(entitiesMutated.size(), 1); + Assert.assertNotNull(entitiesMutated.get(0)); + dbEntity.setGuid(entitiesMutated.get(0).getGuid()); + + this.dbEntity = dbEntity; + } + + private Map<String, Map<String, Object>> populateSuperBusinessMetadataAttributeMap(Map<String, Map<String, Object>> bmAttrMapReq) { + if (bmAttrMapReq == null) { + bmAttrMapReq = new HashMap<>(); + } + Map<String, Object> attrValueMapReq = new HashMap<>(); + attrValueMapReq.put("attrSuperBoolean", true); + attrValueMapReq.put("attrSuperString", "pqr"); + + bmAttrMapReq.put(bmWithSuperType, attrValueMapReq); + return bmAttrMapReq; + } + + private Map<String, Map<String, Object>> populateBusinessMetadataAttributeMap(Map<String, Map<String, Object>> bmAttrMapReq) { + if (bmAttrMapReq == null) { + bmAttrMapReq = new HashMap<>(); + } + Map<String, Object> attrValueMapReq = new HashMap<>(); + attrValueMapReq.put("attr1", true); + attrValueMapReq.put("attr8", "abc"); + + bmAttrMapReq.put(bmWithAllTypes, attrValueMapReq); + return bmAttrMapReq; + } + + private Map<String, Map<String, Object>> populateMultivaluedBusinessMetadataAttributeMap(Map<String, Map<String, Object>> bmAttrMapReq) { + if (bmAttrMapReq == null) { + bmAttrMapReq = new HashMap<>(); + } + Map<String, Object> attrValueMapReq = new HashMap<>(); + + List<Date> dateList = new ArrayList<>(); + Date date = new Date(); + dateList.add(date); + dateList.add(DateUtils.addDays(date, 2)); + attrValueMapReq.put("attr19", dateList); + + List<String> enumList = new ArrayList<>(); + enumList.add("ROLE"); + enumList.add("GROUP"); + attrValueMapReq.put("attr20", enumList); + + bmAttrMapReq.put("bmWithAllTypesMV", attrValueMapReq); + + return bmAttrMapReq; + } + + @Test + public void testDeleteAtlasBusinessTypeDefs() throws AtlasBaseException { + createTestEntity(); + + Map<String, Map<String, Object>> bmAttrMapReq = populateBusinessMetadataAttributeMap(null); + entityREST.addOrUpdateBusinessAttributes(dbEntity.getGuid(), false, bmAttrMapReq); + + AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = entityREST.getById(dbEntity.getGuid(), false, false); + AtlasEntity atlasEntity = entityWithExtInfo.getEntity(); + Map<String, Map<String, Object>> bmAttrMapRes = atlasEntity.getBusinessAttributes(); + + Assert.assertEquals(bmAttrMapReq, bmAttrMapRes); + + AtlasErrorCode errorCode = null; + try { + typesREST.deleteAtlasTypeByName(bmWithAllTypes); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + Map<String, Object> objectMap = bmAttrMapReq.get(bmWithAllTypes); + objectMap.remove("attr1", true); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypes, objectMap); + + errorCode = null; + try { + typesREST.deleteAtlasTypeByName(bmWithAllTypes); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + objectMap.put("attr1", true); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypes, objectMap); + + typesREST.deleteAtlasTypeByName(bmWithAllTypes); + } + + @Test + public void testDeleteAtlasBusinessTypeDefs_2() throws AtlasBaseException { + createTestEntity(); + + Map<String, Map<String, Object>> bmAttrMapReq = populateSuperBusinessMetadataAttributeMap(null); + entityREST.addOrUpdateBusinessAttributes(dbEntity.getGuid(), false, bmAttrMapReq); + + AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = entityREST.getById(dbEntity.getGuid(), false, false); + AtlasEntity atlasEntity = entityWithExtInfo.getEntity(); + Map<String, Map<String, Object>> bmAttrMapRes = atlasEntity.getBusinessAttributes(); + + Assert.assertEquals(bmAttrMapReq, bmAttrMapRes); + + AtlasErrorCode errorCode = null; + try { + typesREST.deleteAtlasTypeByName(bmWithSuperType); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + Map<String, Object> objectMap = bmAttrMapReq.get(bmWithSuperType); + objectMap.remove("attrSuperString", "pqr"); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithSuperType, objectMap); + + errorCode = null; + try { + typesREST.deleteAtlasTypeByName(bmWithSuperType); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + objectMap.put("attrSuperString", "pqr"); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithSuperType, objectMap); + + typesREST.deleteAtlasTypeByName(bmWithSuperType); + } + + @Test + public void testDeleteAtlasBusinessTypeDefs_3() throws AtlasBaseException { + createTestEntity(); + + Map<String, Map<String, Object>> bmAttrMapReq = populateMultivaluedBusinessMetadataAttributeMap(null); + entityREST.addOrUpdateBusinessAttributes(dbEntity.getGuid(), false, bmAttrMapReq); + + AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = entityREST.getById(dbEntity.getGuid(), false, false); + AtlasEntity atlasEntity = entityWithExtInfo.getEntity(); + Map<String, Map<String, Object>> bmAttrMapRes = atlasEntity.getBusinessAttributes(); + + Assert.assertEquals(bmAttrMapReq, bmAttrMapRes); + + AtlasBaseTypeDef atlasBaseTypeDef = typesREST.getTypeDefByName(bmWithAllTypesMV); + AtlasBusinessMetadataDef businessMetadataDef = (AtlasBusinessMetadataDef) atlasBaseTypeDef; + + AtlasTypesDef atlasTypesDef = new AtlasTypesDef(); + atlasTypesDef.setBusinessMetadataDefs(Collections.singletonList(businessMetadataDef)); + + AtlasErrorCode errorCode = null; + try { + typesREST.deleteAtlasTypeDefs(atlasTypesDef); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + Map<String, Object> objectMap = bmAttrMapReq.get(bmWithAllTypesMV); + + List<Date> dateList = (List<Date>) objectMap.get("attr19"); + + objectMap.remove("attr19", dateList); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypesMV, objectMap); + + errorCode = null; + try { + typesREST.deleteAtlasTypeDefs(atlasTypesDef); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + AtlasBusinessMetadataDef atlasBusinessMetadataDef = atlasTypesDef.getBusinessMetadataDefs().get(0); + atlasBusinessMetadataDef.setGuid(""); + atlasTypesDef.setBusinessMetadataDefs(Collections.singletonList(atlasBusinessMetadataDef)); + + errorCode = null; + try { + typesREST.deleteAtlasTypeDefs(atlasTypesDef); + } catch (AtlasBaseException e) { + errorCode = e.getAtlasErrorCode(); + } + Assert.assertEquals(errorCode, AtlasErrorCode.TYPE_HAS_REFERENCES); + + objectMap.put("attr19", dateList); + entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypesMV, objectMap); + + typesREST.deleteAtlasTypeDefs(atlasTypesDef); + } +}