/**
 * 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
 *
 * 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.apache.atlas.repository.graph;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasClient.EntityResult;
import org.apache.atlas.AtlasException;
import org.apache.atlas.CreateUpdateEntitiesResult;
import org.apache.atlas.RequestContext;
import org.apache.atlas.TestOnlyModule;
import org.apache.atlas.TestUtils;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.MetadataRepository;
import org.apache.atlas.repository.RepositoryException;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.Struct;
import org.apache.atlas.typesystem.TypesDef;
import org.apache.atlas.typesystem.exception.EntityExistsException;
import org.apache.atlas.typesystem.exception.EntityNotFoundException;
import org.apache.atlas.typesystem.exception.NullRequiredAttributeException;
import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.types.*;
import org.apache.atlas.typesystem.types.utils.TypesUtil;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.atlas.TestUtils.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

/**
 * Test for GraphBackedMetadataRepository.deleteEntities
 *
 * Guice loads the dependencies and injects the necessary objects
 *
 */
@Guice(modules = TestOnlyModule.class)
public abstract class GraphBackedMetadataRepositoryDeleteTestBase {

    protected MetadataRepository repositoryService;

    private TypeSystem typeSystem;

    private ClassType compositeMapOwnerType;

    private ClassType compositeMapValueType;

    @BeforeClass
    public void setUp() throws Exception {

        typeSystem = TypeSystem.getInstance();
        typeSystem.reset();

        new GraphBackedSearchIndexer(new AtlasTypeRegistry());
        final GraphBackedMetadataRepository delegate = new GraphBackedMetadataRepository(getDeleteHandler(typeSystem));

        repositoryService = TestUtils.addTransactionWrapper(delegate);

        TestUtils.defineDeptEmployeeTypes(typeSystem);
        TestUtils.createHiveTypes(typeSystem);

        // Define type for map value.
        HierarchicalTypeDefinition<ClassType> mapValueDef = TypesUtil.createClassTypeDef("CompositeMapValue",
            ImmutableSet.<String>of(),
            TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE));

        // Define type with map where the value is a composite class reference to MapValue.
        HierarchicalTypeDefinition<ClassType> mapOwnerDef = TypesUtil.createClassTypeDef("CompositeMapOwner",
            ImmutableSet.<String>of(),
            TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE),
            new AttributeDefinition("map", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(),
                        "CompositeMapValue"), Multiplicity.OPTIONAL, true, null));
        TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
            ImmutableList.<StructTypeDefinition>of(), ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
            ImmutableList.of(mapOwnerDef, mapValueDef));
        typeSystem.defineTypes(typesDef);
        compositeMapOwnerType = typeSystem.getDataType(ClassType.class, "CompositeMapOwner");
        compositeMapValueType = typeSystem.getDataType(ClassType.class, "CompositeMapValue");
    }

    abstract DeleteHandler getDeleteHandler(TypeSystem typeSystem);

    @BeforeMethod
    public void setupContext() {
        TestUtils.resetRequestContext();
    }

    @AfterClass
    public void tearDown() throws Exception {
        TypeSystem.getInstance().reset();
        AtlasGraphProvider.cleanup();
    }

    @Test
    public void testDeleteAndCreate() throws Exception {
        Referenceable entity = createDBEntity();
        String id = createInstance(entity);

        //get entity by unique attribute should return the created entity
        ITypedReferenceableInstance instance =
                repositoryService.getEntityDefinition(TestUtils.DATABASE_TYPE, "name", entity.get("name"));
        assertEquals(instance.getId()._getId(), id);

        //delete entity should mark it as deleted
        List<String> results = deleteEntities(id).getDeletedEntities();
        assertEquals(results.get(0), id);
        assertEntityDeleted(id);

        //get entity by unique attribute should throw EntityNotFoundException
        try {
            repositoryService.getEntityDefinition(TestUtils.DATABASE_TYPE, "name", entity.get("name"));
            fail("Expected EntityNotFoundException");
        } catch(EntityNotFoundException e) {
            //expected
        }

        //Create the same entity again, should create new entity
        String newId = createInstance(entity);
        assertNotEquals(id, newId);

        //get by unique attribute should return the new entity
        instance = repositoryService.getEntityDefinition(TestUtils.DATABASE_TYPE, "name", entity.get("name"));
        assertEquals(instance.getId()._getId(), newId);
    }

    @Test
    public void testDeleteEntityWithTraits() throws Exception {
        Referenceable entity = createDBEntity();
        String id = createInstance(entity);

        TraitType dataType = typeSystem.getDataType(TraitType.class, PII);
        ITypedStruct trait = dataType.convert(new Struct(TestUtils.PII), Multiplicity.REQUIRED);
        repositoryService.addTrait(id, trait);

        ITypedReferenceableInstance instance = repositoryService.getEntityDefinition(id);
        assertTrue(instance.getTraits().contains(PII));

        deleteEntities(id);
        assertEntityDeleted(id);
        assertTestDeleteEntityWithTraits(id);
    }

    protected abstract void assertTestDeleteEntityWithTraits(String guid)
            throws EntityNotFoundException, RepositoryException, Exception;

    @Test
    public void testDeleteReference() throws Exception {
        //Deleting column should update table
        Referenceable db = createDBEntity();
        String dbId = createInstance(db);

        Referenceable column = createColumnEntity();
        String colId = createInstance(column);

        Referenceable table = createTableEntity(dbId);
        table.set(COLUMNS_ATTR_NAME, Arrays.asList(new Id(colId, 0, COLUMN_TYPE)));
        String tableId = createInstance(table);

        AtlasClient.EntityResult entityResult = deleteEntities(colId);
        assertEquals(entityResult.getDeletedEntities().size(), 1);
        assertEquals(entityResult.getDeletedEntities().get(0), colId);
        assertEquals(entityResult.getUpdateEntities().size(), 1);
        assertEquals(entityResult.getUpdateEntities().get(0), tableId);

        assertEntityDeleted(colId);

        ITypedReferenceableInstance tableInstance = repositoryService.getEntityDefinition(tableId);
        assertColumnForTestDeleteReference(tableInstance);

        //Deleting table should update process
        Referenceable process = new Referenceable(PROCESS_TYPE);
        process.set(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS, Arrays.asList(new Id(tableId, 0, TABLE_TYPE)));
        String processId = createInstance(process);
        ITypedReferenceableInstance processInstance = repositoryService.getEntityDefinition(processId);

        deleteEntities(tableId);
        assertEntityDeleted(tableId);

        assertTableForTestDeleteReference(tableId);
        assertProcessForTestDeleteReference(processInstance);
    }

    protected abstract void assertTableForTestDeleteReference(String tableId) throws Exception;

    protected abstract void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance)
            throws AtlasException;

    protected abstract void assertProcessForTestDeleteReference(ITypedReferenceableInstance processInstance) throws Exception;

    protected abstract void assertEntityDeleted(String id) throws Exception;

    private AtlasClient.EntityResult deleteEntities(String... id) throws Exception {
        RequestContext.createContext();
        return repositoryService.deleteEntities(Arrays.asList(id));
    }

    private String createInstance(Referenceable entity) throws Exception {
        ClassType dataType = typeSystem.getDataType(ClassType.class, entity.getTypeName());
        ITypedReferenceableInstance instance = dataType.convert(entity, Multiplicity.REQUIRED);
        CreateUpdateEntitiesResult result = repositoryService.createEntities(instance);
        List<String> results = result.getCreatedEntities();
        return results.get(results.size() - 1);
    }

    @Test
    public void testDeleteEntities() throws Exception {
        // Create a table entity, with 3 composite column entities
        Referenceable dbEntity = createDBEntity();
        String dbGuid = createInstance(dbEntity);
        Referenceable table1Entity = createTableEntity(dbGuid);
        Referenceable col1 = createColumnEntity();
        Referenceable col2 = createColumnEntity();
        Referenceable col3 = createColumnEntity();
        table1Entity.set(COLUMNS_ATTR_NAME, ImmutableList.of(col1, col2, col3));
        createInstance(table1Entity);

        // Retrieve the table entities from the Repository, to get their guids and the composite column guids.
        ITypedReferenceableInstance tableInstance = repositoryService.getEntityDefinition(TestUtils.TABLE_TYPE,
                NAME, table1Entity.get(NAME));
        List<IReferenceableInstance> columns = (List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);

        //Delete column
        String colId = columns.get(0).getId()._getId();
        String tableId = tableInstance.getId()._getId();

        AtlasClient.EntityResult entityResult = deleteEntities(colId);
        assertEquals(entityResult.getDeletedEntities().size(), 1);
        assertEquals(entityResult.getDeletedEntities().get(0), colId);
        assertEquals(entityResult.getUpdateEntities().size(), 1);
        assertEquals(entityResult.getUpdateEntities().get(0), tableId);
        assertEntityDeleted(colId);

        tableInstance = repositoryService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, table1Entity.get(NAME));
        assertDeletedColumn(tableInstance);

        //update by removing a column
        tableInstance.set(COLUMNS_ATTR_NAME, ImmutableList.of(col3));
        entityResult = updatePartial(tableInstance);
        colId = columns.get(1).getId()._getId();
        assertEquals(entityResult.getDeletedEntities().size(), 1);
        assertEquals(entityResult.getDeletedEntities().get(0), colId);
        assertEntityDeleted(colId);

        // Delete the table entities.  The deletion should cascade to their composite columns.
        tableInstance = repositoryService.getEntityDefinition(TestUtils.TABLE_TYPE, NAME, table1Entity.get(NAME));
        List<String> deletedGuids = deleteEntities(tableInstance.getId()._getId()).getDeletedEntities();
        assertEquals(deletedGuids.size(), 2);

        // Verify that deleteEntities() response has guids for tables and their composite columns.
        Assert.assertTrue(deletedGuids.contains(tableInstance.getId()._getId()));
        Assert.assertTrue(deletedGuids.contains(columns.get(2).getId()._getId()));

        // Verify that tables and their composite columns have been deleted from the graph Repository.
        for (String guid : deletedGuids) {
            assertEntityDeleted(guid);
        }
        assertTestDeleteEntities(tableInstance);
    }

    protected abstract void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException;

    protected abstract void assertTestDeleteEntities(ITypedReferenceableInstance tableInstance) throws Exception;

    /**
     * Verify deleting entities with composite references to other entities.
     * The composite entities should also be deleted.
     */
    @Test
    public void testDeleteEntitiesWithCompositeArrayReference() throws Exception {
        String hrDeptGuid = createHrDeptGraph();

        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) hrDept.get("employees");
        Assert.assertEquals(employees.size(), 4);

        List<String> employeeGuids = new ArrayList(4);
        for (ITypedReferenceableInstance employee : employees) {
            employeeGuids.add(employee.getId()._getId());
        }

        // There should be 4 vertices for Address structs (one for each Person.address attribute value).
        int vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "Address").size();
        Assert.assertEquals(vertexCount, 4);
        vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "SecurityClearance").size();
        Assert.assertEquals(vertexCount, 1);

        List<String> deletedEntities = deleteEntities(hrDeptGuid).getDeletedEntities();
        assertTrue(deletedEntities.contains(hrDeptGuid));
        assertEntityDeleted(hrDeptGuid);

        // Verify Department entity and its contained Person entities were deleted.
        for (String employeeGuid : employeeGuids) {
            assertTrue(deletedEntities.contains(employeeGuid));
            assertEntityDeleted(employeeGuid);
        }

        // Verify all Person.address struct vertices were removed.
        assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "Address"));

        // Verify all SecurityClearance trait vertices were removed.
        assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "SecurityClearance"));
    }

    protected abstract void assertVerticesDeleted(List<AtlasVertex> vertices);

    @Test
    public void testDeleteEntitiesWithCompositeMapReference() throws Exception {
        // Create instances of MapOwner and MapValue.
        // Set MapOwner.map with one entry that references MapValue instance.
        ITypedReferenceableInstance entityDefinition = createMapOwnerAndValueEntities();
        String mapOwnerGuid = entityDefinition.getId()._getId();

        // Verify MapOwner.map attribute has expected value.
        ITypedReferenceableInstance mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        Object object = mapOwnerInstance.get("map");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof Map);
        Map<String, ITypedReferenceableInstance> map = (Map<String, ITypedReferenceableInstance>)object;
        Assert.assertEquals(map.size(), 1);
        ITypedReferenceableInstance mapValueInstance = map.get("value1");
        Assert.assertNotNull(mapValueInstance);
        String mapValueGuid = mapValueInstance.getId()._getId();
        String edgeLabel = GraphHelper.getEdgeLabel(compositeMapOwnerType, compositeMapOwnerType.fieldMapping.fields.get("map"));
        String mapEntryLabel = edgeLabel + "." + "value1";
        AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(mapEntryLabel);
        AtlasVertex mapOwnerVertex = GraphHelper.getInstance().getVertexForGUID(mapOwnerGuid);
        object = mapOwnerVertex.getProperty(atlasEdgeLabel.getQualifiedMapKey(), Object.class);
        Assert.assertNotNull(object);

        List<String> deletedEntities = deleteEntities(mapOwnerGuid).getDeletedEntities();
        Assert.assertEquals(deletedEntities.size(), 2);
        Assert.assertTrue(deletedEntities.contains(mapOwnerGuid));
        Assert.assertTrue(deletedEntities.contains(mapValueGuid));

        assertEntityDeleted(mapOwnerGuid);
        assertEntityDeleted(mapValueGuid);
    }

    private ITypedReferenceableInstance createMapOwnerAndValueEntities()
        throws AtlasException, RepositoryException, EntityExistsException {

        ITypedReferenceableInstance mapOwnerInstance = compositeMapOwnerType.createInstance();
        mapOwnerInstance.set(NAME, TestUtils.randomString());
        ITypedReferenceableInstance mapValueInstance = compositeMapValueType.createInstance();
        mapValueInstance.set(NAME, TestUtils.randomString());
        mapOwnerInstance.set("map", Collections.singletonMap("value1", mapValueInstance));
        List<String> createEntitiesResult = repositoryService.createEntities(mapOwnerInstance, mapValueInstance).getCreatedEntities();
        Assert.assertEquals(createEntitiesResult.size(), 2);
        ITypedReferenceableInstance entityDefinition = repositoryService.getEntityDefinition("CompositeMapOwner",
            NAME, mapOwnerInstance.get(NAME));
        return entityDefinition;
    }

    private AtlasClient.EntityResult updatePartial(ITypedReferenceableInstance entity) throws RepositoryException {
        RequestContext.createContext();
        return repositoryService.updatePartial(entity).getEntityResult();
    }

    @Test
    public void testUpdateEntity_MultiplicityOneNonCompositeReference() throws Exception {
        String hrDeptGuid = createHrDeptGraph();
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        Map<String, String> nameGuidMap = getEmployeeNameGuidMap(hrDept);

        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
        Id johnGuid = john.getId();

        ITypedReferenceableInstance max = repositoryService.getEntityDefinition(nameGuidMap.get("Max"));
        String maxGuid = max.getId()._getId();
        AtlasVertex vertex = GraphHelper.getInstance().getVertexForGUID(maxGuid);
        Long creationTimestamp = GraphHelper.getSingleValuedProperty(vertex, Constants.TIMESTAMP_PROPERTY_KEY, Long.class);
        Assert.assertNotNull(creationTimestamp);

        Long modificationTimestampPreUpdate = GraphHelper.getSingleValuedProperty(vertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class);
        Assert.assertNotNull(modificationTimestampPreUpdate);

        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
        Id janeId = jane.getId();

        // Update max's mentor reference to john.
        ClassType personType = typeSystem.getDataType(ClassType.class, "Person");
        ITypedReferenceableInstance maxEntity = personType.createInstance(max.getId());
        maxEntity.set("mentor", johnGuid);
        AtlasClient.EntityResult entityResult = updatePartial(maxEntity);
        assertEquals(entityResult.getUpdateEntities().size(), 1);
        assertTrue(entityResult.getUpdateEntities().contains(maxGuid));

        // Verify the update was applied correctly - john should now be max's mentor.
        max = repositoryService.getEntityDefinition(maxGuid);
        ITypedReferenceableInstance refTarget = (ITypedReferenceableInstance) max.get("mentor");
        Assert.assertEquals(refTarget.getId()._getId(), johnGuid._getId());

        // Verify modification timestamp was updated.
        vertex = GraphHelper.getInstance().getVertexForGUID(maxGuid);
        Long modificationTimestampPostUpdate = GraphHelper.getSingleValuedProperty(vertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class);
        Assert.assertNotNull(modificationTimestampPostUpdate);
        Assert.assertTrue(creationTimestamp < modificationTimestampPostUpdate);

        // Update max's mentor reference to jane.
        maxEntity.set("mentor", janeId);
        entityResult = updatePartial(maxEntity);
        assertEquals(entityResult.getUpdateEntities().size(), 1);
        assertTrue(entityResult.getUpdateEntities().contains(maxGuid));

        // Verify the update was applied correctly - jane should now be max's mentor.
        max = repositoryService.getEntityDefinition(maxGuid);
        refTarget = (ITypedReferenceableInstance) max.get("mentor");
        Assert.assertEquals(refTarget.getId()._getId(), janeId._getId());

        // Verify modification timestamp was updated.
        vertex = GraphHelper.getInstance().getVertexForGUID(maxGuid);
        Long modificationTimestampPost2ndUpdate = GraphHelper.getSingleValuedProperty(vertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class);
        Assert.assertNotNull(modificationTimestampPost2ndUpdate);
        Assert.assertTrue(modificationTimestampPostUpdate < modificationTimestampPost2ndUpdate);

        ITypedReferenceableInstance julius = repositoryService.getEntityDefinition(nameGuidMap.get("Julius"));
        Id juliusId = julius.getId();
        maxEntity = personType.createInstance(max.getId());
        maxEntity.set("manager", juliusId);
        entityResult = updatePartial(maxEntity);
        // Verify julius' subordinates were updated.
        assertEquals(entityResult.getUpdateEntities().size(), 3);
        assertTrue(entityResult.getUpdateEntities().contains(maxGuid));
        assertTrue(entityResult.getUpdateEntities().containsAll(Arrays.asList(maxGuid, janeId._getId(), juliusId._getId())));

        // Verify the update was applied correctly - julius should now be max's manager.
        max = repositoryService.getEntityDefinition(maxGuid);
        refTarget = (ITypedReferenceableInstance) max.get("manager");
        Assert.assertEquals(refTarget.getId()._getId(), juliusId._getId());
        Assert.assertEquals(refTarget.getId()._getId(), juliusId._getId());
        julius = repositoryService.getEntityDefinition(nameGuidMap.get("Julius"));
        Object object = julius.get("subordinates");
        Assert.assertTrue(object instanceof List);
        List<ITypedReferenceableInstance> refValues = (List<ITypedReferenceableInstance>) object;
        Assert.assertEquals(refValues.size(), 1);
        Assert.assertTrue(refValues.contains(max.getId()));

        assertTestUpdateEntity_MultiplicityOneNonCompositeReference(janeId._getId());
    }

    protected abstract void assertTestUpdateEntity_MultiplicityOneNonCompositeReference(String janeGuid) throws Exception;

    /**
     * Verify deleting an entity which is contained by another
     * entity through a bi-directional composite reference.
     *
     * @throws Exception
     */
    @Test
    public void testDisconnectBidirectionalReferences() throws Exception {
        String hrDeptGuid = createHrDeptGraph();
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        Map<String, String> nameGuidMap = getEmployeeNameGuidMap(hrDept);
        String maxGuid = nameGuidMap.get("Max");
        String janeGuid = nameGuidMap.get("Jane");
        String johnGuid = nameGuidMap.get("John");

        Assert.assertNotNull(maxGuid);
        Assert.assertNotNull(janeGuid);
        Assert.assertNotNull(johnGuid);

        // Verify that Max is one of Jane's subordinates.
        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(janeGuid);
        Object refValue = jane.get("subordinates");
        Assert.assertTrue(refValue instanceof List);
        List<Object> subordinates = (List<Object>)refValue;
        Assert.assertEquals(subordinates.size(), 2);
        List<String> subordinateIds = new ArrayList<>(2);
        for (Object listValue : subordinates) {
            Assert.assertTrue(listValue instanceof ITypedReferenceableInstance);
            ITypedReferenceableInstance employee = (ITypedReferenceableInstance) listValue;
            subordinateIds.add(employee.getId()._getId());
        }
        Assert.assertTrue(subordinateIds.contains(maxGuid));


        AtlasClient.EntityResult entityResult = deleteEntities(maxGuid);
        ITypedReferenceableInstance john = repositoryService.getEntityDefinition("Person", "name", "John");

        assertEquals(entityResult.getDeletedEntities().size(), 1);
        assertTrue(entityResult.getDeletedEntities().contains(maxGuid));
        assertEquals(entityResult.getUpdateEntities().size(), 3);
        assertTrue(entityResult.getUpdateEntities().containsAll(Arrays.asList(jane.getId()._getId(), hrDeptGuid,
                john.getId()._getId())));
        assertEntityDeleted(maxGuid);

        assertMaxForTestDisconnectBidirectionalReferences(nameGuidMap);

        // Now delete jane - this should disconnect the manager reference from her
        // subordinate.
        entityResult = deleteEntities(janeGuid);
        assertEquals(entityResult.getDeletedEntities().size(), 1);
        assertTrue(entityResult.getDeletedEntities().contains(janeGuid));
        assertEquals(entityResult.getUpdateEntities().size(), 2);
        assertTrue(entityResult.getUpdateEntities().containsAll(Arrays.asList(hrDeptGuid, john.getId()._getId())));

        assertEntityDeleted(janeGuid);

        john = repositoryService.getEntityDefinition("Person", "name", "John");
        assertJohnForTestDisconnectBidirectionalReferences(john, janeGuid);
    }

    protected abstract void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john,
                                                                               String janeGuid) throws Exception;

    protected abstract void assertMaxForTestDisconnectBidirectionalReferences(Map<String, String> nameGuidMap)
            throws Exception;

    /**
     * Verify deleting entity that is the target of a unidirectional class array reference
     * from a class instance.
     */
    @Test
    public void testDisconnectUnidirectionalArrayReferenceFromClassType() throws Exception {
        createDbTableGraph(TestUtils.DATABASE_NAME, TestUtils.TABLE_NAME);

        // Get the guid for one of the table's columns.
        ITypedReferenceableInstance table = repositoryService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", TestUtils.TABLE_NAME);
        String tableGuid = table.getId()._getId();
        List<ITypedReferenceableInstance> columns = (List<ITypedReferenceableInstance>) table.get("columns");
        Assert.assertEquals(columns.size(), 5);
        String columnGuid = columns.get(0).getId()._getId();

        // Delete the column.
        AtlasClient.EntityResult entityResult = deleteEntities(columnGuid);
        assertEquals(entityResult.getDeletedEntities().size(), 1);
        Assert.assertTrue(entityResult.getDeletedEntities().contains(columnGuid));
        assertEquals(entityResult.getUpdateEntities().size(), 1);
        Assert.assertTrue(entityResult.getUpdateEntities().contains(tableGuid));
        assertEntityDeleted(columnGuid);

        // Verify table.columns reference to the deleted column has been disconnected.
        table = repositoryService.getEntityDefinition(tableGuid);
        assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
                (List<ITypedReferenceableInstance>) table.get("columns"), columnGuid);
    }

    protected abstract void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
            List<ITypedReferenceableInstance> columns, String columnGuid);

    /**
     * Verify deleting entities that are the target of a unidirectional class array reference
     * from a struct or trait instance.
     */
    @Test
    public void testDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes() throws Exception {
        // Define class types.
        HierarchicalTypeDefinition<ClassType> structTargetDef = TypesUtil.createClassTypeDef("StructTarget",
            ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
        HierarchicalTypeDefinition<ClassType> traitTargetDef = TypesUtil.createClassTypeDef("TraitTarget",
            ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
        HierarchicalTypeDefinition<ClassType> structContainerDef = TypesUtil.createClassTypeDef("StructContainer",
            ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("struct", "TestStruct"));

        // Define struct and trait types which have a unidirectional array reference
        // to a class type.
        StructTypeDefinition structDef = TypesUtil.createStructTypeDef("TestStruct",
            new AttributeDefinition("target", DataTypes.arrayTypeName("StructTarget"), Multiplicity.OPTIONAL, false, null),
            new AttributeDefinition("nestedStructs", DataTypes.arrayTypeName("NestedStruct"), Multiplicity.OPTIONAL, false, null));
        StructTypeDefinition nestedStructDef = TypesUtil.createStructTypeDef("NestedStruct",
            TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
        HierarchicalTypeDefinition<TraitType> traitDef = TypesUtil.createTraitTypeDef("TestTrait", ImmutableSet.<String>of(),
            new AttributeDefinition("target", DataTypes.arrayTypeName("TraitTarget"), Multiplicity.OPTIONAL, false, null));

        TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.of(structDef, nestedStructDef),
            ImmutableList.of(traitDef), ImmutableList.of(structTargetDef, traitTargetDef, structContainerDef));
        typeSystem.defineTypes(typesDef);

        // Create instances of class, struct, and trait types.
        Referenceable structTargetEntity = new Referenceable("StructTarget");
        Referenceable traitTargetEntity = new Referenceable("TraitTarget");
        Referenceable structContainerEntity = new Referenceable("StructContainer");
        Struct structInstance = new Struct("TestStruct");
        Struct nestedStructInstance = new Struct("NestedStruct");
        Referenceable traitInstance = new Referenceable("TestTrait");
        structContainerEntity.set("struct", structInstance);
        structInstance.set("target", ImmutableList.of(structTargetEntity));
        structInstance.set("nestedStructs", ImmutableList.of(nestedStructInstance));

        ClassType structTargetType = typeSystem.getDataType(ClassType.class, "StructTarget");
        ClassType traitTargetType = typeSystem.getDataType(ClassType.class, "TraitTarget");
        ClassType structContainerType = typeSystem.getDataType(ClassType.class, "StructContainer");

        ITypedReferenceableInstance structTargetConvertedEntity =
            structTargetType.convert(structTargetEntity, Multiplicity.REQUIRED);
        ITypedReferenceableInstance traitTargetConvertedEntity =
            traitTargetType.convert(traitTargetEntity, Multiplicity.REQUIRED);
        ITypedReferenceableInstance structContainerConvertedEntity =
            structContainerType.convert(structContainerEntity, Multiplicity.REQUIRED);

        List<String> guids = repositoryService.createEntities(
            structTargetConvertedEntity, traitTargetConvertedEntity, structContainerConvertedEntity).getCreatedEntities();
        Assert.assertEquals(guids.size(), 3);

        guids = repositoryService.getEntityList("StructTarget");
        Assert.assertEquals(guids.size(), 1);
        String structTargetGuid = guids.get(0);

        guids = repositoryService.getEntityList("TraitTarget");
        Assert.assertEquals(guids.size(), 1);
        String traitTargetGuid = guids.get(0);

        guids = repositoryService.getEntityList("StructContainer");
        Assert.assertEquals(guids.size(), 1);
        String structContainerGuid = guids.get(0);

        // Add TestTrait to StructContainer instance
        traitInstance.set("target", ImmutableList.of(new Id(traitTargetGuid, 0, "TraitTarget")));
        TraitType traitType = typeSystem.getDataType(TraitType.class, "TestTrait");
        ITypedStruct convertedTrait = traitType.convert(traitInstance, Multiplicity.REQUIRED);
        repositoryService.addTrait(structContainerGuid, convertedTrait);

        // Verify that the unidirectional references from the struct and trait instances
        // are pointing at the target entities.
        structContainerConvertedEntity = repositoryService.getEntityDefinition(structContainerGuid);
        Object object = structContainerConvertedEntity.get("struct");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof ITypedStruct);
        ITypedStruct struct = (ITypedStruct) object;
        object = struct.get("target");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof List);
        List<ITypedReferenceableInstance> refList = (List<ITypedReferenceableInstance>)object;
        Assert.assertEquals(refList.size(), 1);
        Assert.assertEquals(refList.get(0).getId()._getId(), structTargetGuid);

        IStruct trait = structContainerConvertedEntity.getTrait("TestTrait");
        Assert.assertNotNull(trait);
        object = trait.get("target");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof List);
        refList = (List<ITypedReferenceableInstance>)object;
        Assert.assertEquals(refList.size(), 1);
        Assert.assertEquals(refList.get(0).getId()._getId(), traitTargetGuid);

        // Delete the entities that are targets of the struct and trait instances.
        AtlasClient.EntityResult entityResult = deleteEntities(structTargetGuid, traitTargetGuid);
        Assert.assertEquals(entityResult.getDeletedEntities().size(), 2);
        Assert.assertTrue(entityResult.getDeletedEntities().containsAll(Arrays.asList(structTargetGuid, traitTargetGuid)));
        assertEntityDeleted(structTargetGuid);
        assertEntityDeleted(traitTargetGuid);

        assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(structContainerGuid);

        // Delete the entity which contains nested structs and has the TestTrait trait.
        entityResult = deleteEntities(structContainerGuid);
        Assert.assertEquals(entityResult.getDeletedEntities().size(), 1);
        Assert.assertTrue(entityResult.getDeletedEntities().contains(structContainerGuid));
        assertEntityDeleted(structContainerGuid);

        // Verify all TestStruct struct vertices were removed.
        assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "TestStruct"));

        // Verify all NestedStruct struct vertices were removed.
        assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "NestedStruct"));

        // Verify all TestTrait trait vertices were removed.
        assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "TestTrait"));
    }

    protected abstract void assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(
            String structContainerGuid) throws Exception;

    /**
     * Verify deleting entities that are the target of class map references.
     */
    @Test
    public void testDisconnectMapReferenceFromClassType() throws Exception {
        // Define type for map value.
        HierarchicalTypeDefinition<ClassType> mapValueDef = TypesUtil.createClassTypeDef("MapValue",
            ImmutableSet.<String>of(),
            new AttributeDefinition("biMapOwner", "MapOwner", Multiplicity.OPTIONAL, false, "biMap"));

        // Define type with unidirectional and bidirectional map references,
        // where the map value is a class reference to MapValue.
        HierarchicalTypeDefinition<ClassType> mapOwnerDef = TypesUtil.createClassTypeDef("MapOwner",
            ImmutableSet.<String>of(),
            new AttributeDefinition("map", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(),
                        "MapValue"), Multiplicity.OPTIONAL, false, null),
            new AttributeDefinition("biMap", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(),
                "MapValue"), Multiplicity.OPTIONAL, false, "biMapOwner"));
        TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
            ImmutableList.<StructTypeDefinition>of(), ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
            ImmutableList.of(mapOwnerDef, mapValueDef));
        typeSystem.defineTypes(typesDef);
        ClassType mapOwnerType = typeSystem.getDataType(ClassType.class, "MapOwner");
        ClassType mapValueType = typeSystem.getDataType(ClassType.class, "MapValue");

        // Create instances of MapOwner and MapValue.
        // Set MapOwner.map and MapOwner.biMap with one entry that references MapValue instance.
        ITypedReferenceableInstance mapOwnerInstance = mapOwnerType.createInstance();
        ITypedReferenceableInstance mapValueInstance = mapValueType.createInstance();
        mapOwnerInstance.set("map", Collections.singletonMap("value1", mapValueInstance));
        mapOwnerInstance.set("biMap", Collections.singletonMap("value1", mapValueInstance));
        // Set biMapOwner reverse reference on MapValue.
        mapValueInstance.set("biMapOwner", mapOwnerInstance);
        List<String> createEntitiesResult = repositoryService.createEntities(mapOwnerInstance, mapValueInstance).getCreatedEntities();
        Assert.assertEquals(createEntitiesResult.size(), 2);
        List<String> guids = repositoryService.getEntityList("MapOwner");
        Assert.assertEquals(guids.size(), 1);
        String mapOwnerGuid = guids.get(0);

        String edgeLabel = GraphHelper.getEdgeLabel(mapOwnerType, mapOwnerType.fieldMapping.fields.get("map"));
        String mapEntryLabel = edgeLabel + "." + "value1";
        AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(mapEntryLabel);

        // Verify MapOwner.map attribute has expected value.
        String mapValueGuid = null;
        AtlasVertex mapOwnerVertex = null;
        mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        for (String mapAttrName : Arrays.asList("map", "biMap")) {
            Object object = mapOwnerInstance.get(mapAttrName);
            Assert.assertNotNull(object);
            Assert.assertTrue(object instanceof Map);
            Map<String, ITypedReferenceableInstance> map = (Map<String, ITypedReferenceableInstance>)object;
            Assert.assertEquals(map.size(), 1);
            mapValueInstance = map.get("value1");
            Assert.assertNotNull(mapValueInstance);
            mapValueGuid = mapValueInstance.getId()._getId();
            mapOwnerVertex = GraphHelper.getInstance().getVertexForGUID(mapOwnerGuid);
            object = mapOwnerVertex.getProperty(atlasEdgeLabel.getQualifiedMapKey(), Object.class);
            Assert.assertNotNull(object);
        }

        // Delete the map value instance.
        // This should disconnect the references from the map owner instance.
        deleteEntities(mapValueGuid);
        assertEntityDeleted(mapValueGuid);
        assertTestDisconnectMapReferenceFromClassType(mapOwnerGuid);
    }

    protected abstract void assertTestDisconnectMapReferenceFromClassType(String mapOwnerGuid) throws Exception;

    @Test
    public void testDeleteTargetOfMultiplicityOneRequiredReference() throws Exception {
        createDbTableGraph("db1", "table1");
        ITypedReferenceableInstance db = repositoryService.getEntityDefinition(TestUtils.DATABASE_TYPE, "name", "db1");
        try {
            // table1 references db1 through the required reference hive_table.database.
            // Attempt to delete db1 should cause a NullRequiredAttributeException,
            // as that would violate the lower bound on table1's database attribute.
            deleteEntities(db.getId()._getId());
            Assert.fail("Lower bound on attribute hive_table.database was not enforced - " +
                NullRequiredAttributeException.class.getSimpleName() + " was expected but none thrown");
        }
        catch (Exception e) {
            verifyExceptionThrown(e, NullRequiredAttributeException.class);
        }

        // Delete table1.
        ITypedReferenceableInstance table1 = repositoryService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", "table1");
        Assert.assertNotNull(table1);
        deleteEntities(table1.getId()._getId());

        // Now delete of db1 should succeed, since it is no longer the target
        // of the required reference from the deleted table1.
        deleteEntities(db.getId()._getId());
    }

    @Test
    public void testDeleteTargetOfMultiplicityManyRequiredReference() throws Exception {
        String deptGuid = createHrDeptGraph();
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(deptGuid);
        Map<String, String> nameGuidMap = getEmployeeNameGuidMap(hrDept);

        // Delete John - this should work, as it would reduce the cardinality of Jane's subordinates reference
        // from 2 to 1.
        deleteEntities(nameGuidMap.get("John"));

        // Attempt to delete Max - this should cause a NullRequiredAttributeException,
        // as that would reduce the cardinality on Jane's subordinates reference from 1 to 0
        // and violate the lower bound.
        try {
            deleteEntities(nameGuidMap.get("Max"));
            assertTestDeleteTargetOfMultiplicityRequiredReference();
        }
        catch (Exception e) {
            verifyExceptionThrown(e, NullRequiredAttributeException.class);
        }
    }

    protected abstract void assertTestDeleteTargetOfMultiplicityRequiredReference() throws Exception;

    @Test
    public void testDeleteTargetOfRequiredMapReference() throws Exception {
        // Define type for map value.
        HierarchicalTypeDefinition<ClassType> mapValueDef = TypesUtil.createClassTypeDef("RequiredMapValue",
            ImmutableSet.<String>of());

        // Define type with required map references where the map value is a class reference to RequiredMapValue.
        HierarchicalTypeDefinition<ClassType> mapOwnerDef = TypesUtil.createClassTypeDef("RequiredMapOwner",
            ImmutableSet.<String>of(),
            new AttributeDefinition("map", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(),
                        "RequiredMapValue"), Multiplicity.REQUIRED, false, null));
        TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
            ImmutableList.<StructTypeDefinition>of(), ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
            ImmutableList.of(mapOwnerDef, mapValueDef));
        typeSystem.defineTypes(typesDef);
        ClassType mapOwnerType = typeSystem.getDataType(ClassType.class, "RequiredMapOwner");
        ClassType mapValueType = typeSystem.getDataType(ClassType.class, "RequiredMapValue");

        // Create instances of RequiredMapOwner and RequiredMapValue.
        // Set RequiredMapOwner.map with one entry that references RequiredMapValue instance.
        ITypedReferenceableInstance mapOwnerInstance = mapOwnerType.createInstance();
        ITypedReferenceableInstance mapValueInstance = mapValueType.createInstance();
        mapOwnerInstance.set("map", Collections.singletonMap("value1", mapValueInstance));
        List<String> createEntitiesResult = repositoryService.createEntities(mapOwnerInstance, mapValueInstance).getCreatedEntities();
        Assert.assertEquals(createEntitiesResult.size(), 2);
        List<String> guids = repositoryService.getEntityList("RequiredMapOwner");
        Assert.assertEquals(guids.size(), 1);
        String mapOwnerGuid = guids.get(0);
        guids = repositoryService.getEntityList("RequiredMapValue");
        Assert.assertEquals(guids.size(), 1);
        String mapValueGuid = guids.get(0);

        // Verify MapOwner.map attribute has expected value.
        mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        Object object = mapOwnerInstance.get("map");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof Map);
        Map<String, ITypedReferenceableInstance> map = (Map<String, ITypedReferenceableInstance>)object;
        Assert.assertEquals(map.size(), 1);
        mapValueInstance = map.get("value1");
        Assert.assertNotNull(mapValueInstance);
        Assert.assertEquals(mapValueInstance.getId()._getId(), mapValueGuid);
        String edgeLabel = GraphHelper.getEdgeLabel(mapOwnerType, mapOwnerType.fieldMapping.fields.get("map"));
        String mapEntryLabel = edgeLabel + "." + "value1";
        AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(mapEntryLabel);
        AtlasVertex mapOwnerVertex = GraphHelper.getInstance().getVertexForGUID(mapOwnerGuid);
        object = mapOwnerVertex.getProperty(atlasEdgeLabel.getQualifiedMapKey(), Object.class);
        Assert.assertNotNull(object);

        // Verify deleting the target of required map attribute throws a NullRequiredAttributeException.
        try {
            deleteEntities(mapValueGuid);
            Assert.fail(NullRequiredAttributeException.class.getSimpleName() + " was expected but none thrown.");
        }
        catch (Exception e) {
            verifyExceptionThrown(e, NullRequiredAttributeException.class);
        }
    }

    @Test
    public void testLowerBoundsIgnoredOnDeletedEntities() throws Exception {

        String hrDeptGuid = createHrDeptGraph();
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        Map<String, String> nameGuidMap = getEmployeeNameGuidMap(hrDept);

        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
        String johnGuid = john.getId()._getId();

        ITypedReferenceableInstance max = repositoryService.getEntityDefinition(nameGuidMap.get("Max"));
        String maxGuid = max.getId()._getId();

        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
        String janeGuid = jane.getId()._getId();

        // The lower bound constraint on Manager.subordinates should not be enforced on Jane since that entity is being deleted.
        // Prior to the fix for ATLAS-991, this call would fail with a NullRequiredAttributeException.
        EntityResult deleteResult = deleteEntities(johnGuid, maxGuid, janeGuid);
        Assert.assertEquals(deleteResult.getDeletedEntities().size(), 3);
        Assert.assertTrue(deleteResult.getDeletedEntities().containsAll(Arrays.asList(johnGuid, maxGuid, janeGuid)));
        Assert.assertEquals(deleteResult.getUpdateEntities().size(), 1);

        // Verify that Department entity was updated to disconnect its references to the deleted employees.
        Assert.assertEquals(deleteResult.getUpdateEntities().get(0), hrDeptGuid);
        hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        Object object = hrDept.get("employees");
        Assert.assertTrue(object instanceof List);
        List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) object;
        assertTestLowerBoundsIgnoredOnDeletedEntities(employees);
    }

    protected abstract void assertTestLowerBoundsIgnoredOnDeletedEntities(List<ITypedReferenceableInstance> employees);

    @Test
    public void testLowerBoundsIgnoredOnCompositeDeletedEntities() throws Exception {
        String hrDeptGuid = createHrDeptGraph();
        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
        Map<String, String> nameGuidMap = getEmployeeNameGuidMap(hrDept);
        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
        String johnGuid = john.getId()._getId();
        ITypedReferenceableInstance max = repositoryService.getEntityDefinition(nameGuidMap.get("Max"));
        String maxGuid = max.getId()._getId();

        // The lower bound constraint on Manager.subordinates should not be enforced on the composite entity
        // for Jane owned by the Department entity, since that entity is being deleted.
        // Prior to the fix for ATLAS-991, this call would fail with a NullRequiredAttributeException.
        EntityResult deleteResult = deleteEntities(johnGuid, maxGuid, hrDeptGuid);
        Assert.assertEquals(deleteResult.getDeletedEntities().size(), 5);
        Assert.assertTrue(deleteResult.getDeletedEntities().containsAll(nameGuidMap.values()));
        Assert.assertTrue(deleteResult.getDeletedEntities().contains(hrDeptGuid));
        assertTestLowerBoundsIgnoredOnCompositeDeletedEntities(hrDeptGuid);
    }


    protected abstract void assertTestLowerBoundsIgnoredOnCompositeDeletedEntities(String hrDeptGuid) throws Exception;

    @Test
    public void testLowerBoundsIgnoredWhenDeletingCompositeEntitesOwnedByMap() throws Exception {
        // Define MapValueReferencer type with required reference to CompositeMapValue.
        HierarchicalTypeDefinition<ClassType> mapValueReferencerTypeDef = TypesUtil.createClassTypeDef("MapValueReferencer",
            ImmutableSet.<String>of(),
            new AttributeDefinition("refToMapValue", "CompositeMapValue", Multiplicity.REQUIRED, false, null));

        // Define MapValueReferencerContainer type with required composite map reference to MapValueReferencer.
        HierarchicalTypeDefinition<ClassType> mapValueReferencerContainerTypeDef =
            TypesUtil.createClassTypeDef("MapValueReferencerContainer",
            ImmutableSet.<String>of(),
            new AttributeDefinition("requiredMap", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(), "MapValueReferencer"), Multiplicity.REQUIRED, true, null));

        Map<String, IDataType> definedClassTypes = typeSystem.defineClassTypes(mapValueReferencerTypeDef, mapValueReferencerContainerTypeDef);
        ClassType mapValueReferencerClassType = (ClassType) definedClassTypes.get("MapValueReferencer");
        ClassType mapValueReferencerContainerType = (ClassType) definedClassTypes.get("MapValueReferencerContainer");

        // Create instances of CompositeMapOwner and CompositeMapValue.
        // Set MapOwner.map with one entry that references MapValue instance.
        ITypedReferenceableInstance entityDefinition = createMapOwnerAndValueEntities();
        String mapOwnerGuid = entityDefinition.getId()._getId();

        // Verify MapOwner.map attribute has expected value.
        ITypedReferenceableInstance mapOwnerInstance = repositoryService.getEntityDefinition(mapOwnerGuid);
        Object object = mapOwnerInstance.get("map");
        Assert.assertNotNull(object);
        Assert.assertTrue(object instanceof Map);
        Map<String, ITypedReferenceableInstance> map = (Map<String, ITypedReferenceableInstance>)object;
        Assert.assertEquals(map.size(), 1);
        ITypedReferenceableInstance mapValueInstance = map.get("value1");
        Assert.assertNotNull(mapValueInstance);
        String mapValueGuid = mapValueInstance.getId()._getId();

        // Create instance of MapValueReferencerContainer
        RequestContext.createContext();
        ITypedReferenceableInstance mapValueReferencerContainer = mapValueReferencerContainerType.createInstance();
        List<String> createdEntities = repositoryService.createEntities(mapValueReferencerContainer).getCreatedEntities();
        Assert.assertEquals(createdEntities.size(), 1);
        String mapValueReferencerContainerGuid = createdEntities.get(0);
        mapValueReferencerContainer = repositoryService.getEntityDefinition(createdEntities.get(0));

        // Create instance of MapValueReferencer, and update mapValueReferencerContainer
        // to reference it.
        ITypedReferenceableInstance mapValueReferencer = mapValueReferencerClassType.createInstance();
        mapValueReferencerContainer.set("requiredMap", Collections.singletonMap("value1", mapValueReferencer));
        mapValueReferencer.set("refToMapValue", mapValueInstance.getId());

        RequestContext.createContext();
        EntityResult updateEntitiesResult = repositoryService.updateEntities(mapValueReferencerContainer).getEntityResult();
        Assert.assertEquals(updateEntitiesResult.getCreatedEntities().size(), 1);
        Assert.assertEquals(updateEntitiesResult.getUpdateEntities().size(), 1);
        Assert.assertEquals(updateEntitiesResult.getUpdateEntities().get(0), mapValueReferencerContainerGuid);
        String mapValueReferencerGuid = updateEntitiesResult.getCreatedEntities().get(0);

        // Delete map owner and map referencer container.  A total of 4 entities should be deleted,
        // including the composite entities.  The lower bound constraint on MapValueReferencer.refToMapValue
        // should not be enforced on the composite MapValueReferencer since it is being deleted.
        EntityResult deleteEntitiesResult = repositoryService.deleteEntities(Arrays.asList(mapOwnerGuid, mapValueReferencerContainerGuid));
        Assert.assertEquals(deleteEntitiesResult.getDeletedEntities().size(), 4);
        Assert.assertTrue(deleteEntitiesResult.getDeletedEntities().containsAll(
            Arrays.asList(mapOwnerGuid, mapValueGuid, mapValueReferencerContainerGuid, mapValueReferencerGuid)));
    }

    @Test
    public void testDeleteMixOfExistentAndNonExistentEntities() throws Exception {
        ITypedReferenceableInstance entity1 = compositeMapValueType.createInstance();
        ITypedReferenceableInstance entity2 = compositeMapValueType.createInstance();
        List<String> createEntitiesResult = repositoryService.createEntities(entity1, entity2).getCreatedEntities();
        Assert.assertEquals(createEntitiesResult.size(), 2);
        List<String> guids = Arrays.asList(createEntitiesResult.get(0), "non-existent-guid1", "non-existent-guid2", createEntitiesResult.get(1));
        EntityResult deleteEntitiesResult = repositoryService.deleteEntities(guids);
        Assert.assertEquals(deleteEntitiesResult.getDeletedEntities().size(), 2);
        Assert.assertTrue(deleteEntitiesResult.getDeletedEntities().containsAll(createEntitiesResult));
    }

    @Test
    public void testDeleteMixOfNullAndNonNullGuids() throws Exception {
        ITypedReferenceableInstance entity1 = compositeMapValueType.createInstance();
        ITypedReferenceableInstance entity2 = compositeMapValueType.createInstance();
        List<String> createEntitiesResult = repositoryService.createEntities(entity1, entity2).getCreatedEntities();
        Assert.assertEquals(createEntitiesResult.size(), 2);
        List<String> guids = Arrays.asList(createEntitiesResult.get(0), null, null, createEntitiesResult.get(1));
        EntityResult deleteEntitiesResult = repositoryService.deleteEntities(guids);
        Assert.assertEquals(deleteEntitiesResult.getDeletedEntities().size(), 2);
        Assert.assertTrue(deleteEntitiesResult.getDeletedEntities().containsAll(createEntitiesResult));
    }

    @Test
    public void testDeleteCompositeEntityAndContainer() throws Exception {
        Referenceable db = createDBEntity();
        String dbId = createInstance(db);

        Referenceable column = createColumnEntity();
        String colId = createInstance(column);

        Referenceable table1 = createTableEntity(dbId);
        table1.set(COLUMNS_ATTR_NAME, Arrays.asList(new Id(colId, 0, COLUMN_TYPE)));
        String table1Id = createInstance(table1);
        Referenceable table2 = createTableEntity(dbId);
        String table2Id = createInstance(table2);

        // Delete the tables and column
        AtlasClient.EntityResult entityResult = deleteEntities(table1Id, colId, table2Id);
        Assert.assertEquals(entityResult.getDeletedEntities().size(), 3);
        Assert.assertTrue(entityResult.getDeletedEntities().containsAll(Arrays.asList(colId, table1Id, table2Id)));
        assertEntityDeleted(table1Id);
        assertEntityDeleted(colId);
        assertEntityDeleted(table2Id);
    }

    @Test
    public void testDeleteEntityWithDuplicateReferenceListElements() throws Exception {
        // Create a table entity, with 2 composite column entities
        Referenceable dbEntity = createDBEntity();
        String dbGuid = createInstance(dbEntity);
        Referenceable table1Entity = createTableEntity(dbGuid);
        String tableName = TestUtils.randomString();
        table1Entity.set(NAME, tableName);
        Referenceable col1 = createColumnEntity();
        col1.set(NAME, TestUtils.randomString());
        Referenceable col2 = createColumnEntity();
        col2.set(NAME, TestUtils.randomString());
        // Populate columns reference list with duplicates.
        table1Entity.set(COLUMNS_ATTR_NAME, ImmutableList.of(col1, col2, col1, col2));
        ClassType dataType = typeSystem.getDataType(ClassType.class, table1Entity.getTypeName());
        ITypedReferenceableInstance instance = dataType.convert(table1Entity, Multiplicity.REQUIRED);
        TestUtils.resetRequestContext();
        List<String> result = repositoryService.createEntities(instance).getCreatedEntities();
        Assert.assertEquals(result.size(), 3);
        ITypedReferenceableInstance entityDefinition = repositoryService.getEntityDefinition(TABLE_TYPE, NAME, tableName);
        String tableGuid = entityDefinition.getId()._getId();
        Object attrValue = entityDefinition.get(COLUMNS_ATTR_NAME);
        assertTrue(attrValue instanceof List);
        List<ITypedReferenceableInstance> columns = (List<ITypedReferenceableInstance>) attrValue;
        Assert.assertEquals(columns.size(), 4);
        TestUtils.resetRequestContext();
        String columnGuid = columns.get(0).getId()._getId();

        // Delete one of the columns.
        EntityResult deleteResult = repositoryService.deleteEntities(Collections.singletonList(columnGuid));
        Assert.assertEquals(deleteResult.getDeletedEntities().size(), 1);
        Assert.assertTrue(deleteResult.getDeletedEntities().contains(columnGuid));
        Assert.assertEquals(deleteResult.getUpdateEntities().size(), 1);
        Assert.assertTrue(deleteResult.getUpdateEntities().contains(tableGuid));

        // Verify the duplicate edge IDs were all removed from reference property list.
        AtlasVertex tableVertex = GraphHelper.getInstance().getVertexForGUID(tableGuid);
        String columnsPropertyName = GraphHelper.getQualifiedFieldName(dataType, COLUMNS_ATTR_NAME);
        List columnsPropertyValue = tableVertex.getProperty(columnsPropertyName, List.class);
        verifyTestDeleteEntityWithDuplicateReferenceListElements(columnsPropertyValue);
    }

    protected abstract void verifyTestDeleteEntityWithDuplicateReferenceListElements(List columnsPropertyValue);

    private String createHrDeptGraph() throws Exception {
        ITypedReferenceableInstance hrDept = TestUtils.createDeptEg1(typeSystem);

        List<String> guids = repositoryService.createEntities(hrDept).getCreatedEntities();
        Assert.assertNotNull(guids);
        Assert.assertEquals(guids.size(), 5);

        return getDepartmentGuid(guids);
    }

    private String getDepartmentGuid(List<String> guids)
        throws RepositoryException, EntityNotFoundException {

        String hrDeptGuid = null;
        for (String guid : guids) {
            ITypedReferenceableInstance entityDefinition = repositoryService.getEntityDefinition(guid);
            Id id = entityDefinition.getId();
            if (id.getTypeName().equals("Department")) {
                hrDeptGuid = id._getId();
                break;
            }
        }
        if (hrDeptGuid == null) {
            Assert.fail("Entity for type Department not found");
        }
        return hrDeptGuid;
    }

    private void createDbTableGraph(String dbName, String tableName) throws Exception {
        Referenceable databaseInstance = new Referenceable(TestUtils.DATABASE_TYPE);
        databaseInstance.set("name", dbName);
        databaseInstance.set("description", "foo database");

        ClassType dbType = typeSystem.getDataType(ClassType.class, TestUtils.DATABASE_TYPE);
        ITypedReferenceableInstance db = dbType.convert(databaseInstance, Multiplicity.REQUIRED);
        Referenceable tableInstance = new Referenceable(TestUtils.TABLE_TYPE, TestUtils.CLASSIFICATION);
        tableInstance.set("name", tableName);
        tableInstance.set("description", "bar table");
        tableInstance.set("type", "managed");
        Struct traitInstance = (Struct) tableInstance.getTrait(TestUtils.CLASSIFICATION);
        traitInstance.set("tag", "foundation_etl");
        tableInstance.set("tableType", 1); // enum

        tableInstance.set("database", databaseInstance);
        ArrayList<Referenceable> columns = new ArrayList<>();
        for (int index = 0; index < 5; index++) {
            Referenceable columnInstance = new Referenceable("column_type");
            final String name = "column_" + index;
            columnInstance.set("name", name);
            columnInstance.set("type", "string");
            columns.add(columnInstance);
        }
        tableInstance.set("columns", columns);
        ClassType tableType = typeSystem.getDataType(ClassType.class, TestUtils.TABLE_TYPE);
        ITypedReferenceableInstance table = tableType.convert(tableInstance, Multiplicity.REQUIRED);
        repositoryService.createEntities(db, table);
    }

    protected List<AtlasVertex> getVertices(String propertyName, Object value) {
        AtlasGraph graph = TestUtils.getGraph();
        Iterable<AtlasVertex> vertices = graph.getVertices(propertyName, value);
        List<AtlasVertex> list = new ArrayList<>();
        for (AtlasVertex vertex : vertices) {
            list.add(vertex);
        }
        return list;
    }

    private Map<String, String> getEmployeeNameGuidMap(final ITypedReferenceableInstance hrDept) throws AtlasException {
        Object refValue = hrDept.get("employees");
        Assert.assertTrue(refValue instanceof List);
        List<Object> employees = (List<Object>)refValue;
        Assert.assertEquals(employees.size(), 4);
        Map<String, String> nameGuidMap = new HashMap<String, String>() {{
            put("hr", hrDept.getId()._getId());
        }};

        for (Object listValue : employees) {
            Assert.assertTrue(listValue instanceof ITypedReferenceableInstance);
            ITypedReferenceableInstance employee = (ITypedReferenceableInstance) listValue;
            nameGuidMap.put((String)employee.get("name"), employee.getId()._getId());
        }
        return nameGuidMap;
    }

    /**
     * Search exception cause chain for specified exception.
     *
     * @param thrown root of thrown exception chain
     * @param expected  class of expected exception
     */
    private void verifyExceptionThrown(Exception thrown, Class expected) {

        boolean exceptionFound = false;
        Throwable cause = thrown;
        while (cause != null) {
            if (expected.isInstance(cause)) {
                // good
                exceptionFound = true;
                break;
            }
            else {
                cause = cause.getCause();
            }
        }
        if (!exceptionFound) {
            Assert.fail(expected.getSimpleName() + " was expected but not thrown", thrown);
        }
    }
}
