Repository: incubator-atlas
Updated Branches:
  refs/heads/master c7540b38f -> aa67f8aee


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aa67f8ae/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasDeleteHandlerV1Test.java
----------------------------------------------------------------------
diff --git 
a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasDeleteHandlerV1Test.java
 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasDeleteHandlerV1Test.java
new file mode 100644
index 0000000..b35d288
--- /dev/null
+++ 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasDeleteHandlerV1Test.java
@@ -0,0 +1,791 @@
+/**
+ * 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.repository.store.graph.v1;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.RepositoryMetadataModule;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.TestUtils;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasStruct;
+import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.model.instance.EntityMutations;
+import org.apache.atlas.model.typedef.AtlasClassificationDef;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.model.typedef.AtlasTypesDef;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasGraph;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.services.MetadataService;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.type.AtlasTypeUtil;
+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.Struct;
+import org.apache.atlas.typesystem.exception.EntityNotFoundException;
+import org.apache.atlas.typesystem.persistence.Id;
+import org.apache.atlas.typesystem.types.Multiplicity;
+import org.apache.atlas.typesystem.types.TraitType;
+import org.apache.atlas.typesystem.types.TypeSystem;
+import org.apache.atlas.util.AtlasRepositoryConfiguration;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+
+import java.lang.reflect.Constructor;
+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.COLUMNS_ATTR_NAME;
+import static org.apache.atlas.TestUtils.COLUMN_TYPE;
+import static org.apache.atlas.TestUtils.DEPARTMENT_TYPE;
+import static org.apache.atlas.TestUtils.NAME;
+import static org.apache.atlas.TestUtils.TABLE_TYPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+@Guice(modules = RepositoryMetadataModule.class)
+public abstract class AtlasDeleteHandlerV1Test {
+
+    @Inject
+    AtlasTypeRegistry typeRegistry;
+
+    @Inject
+    AtlasTypeDefStore typeDefStore;
+
+    AtlasEntityStore entityStore;
+
+    @Inject
+    MetadataService metadataService;
+
+    private AtlasEntityType compositeMapOwnerType;
+
+    private AtlasEntityType compositeMapValueType;
+
+    private TypeSystem typeSystem = TypeSystem.getInstance();
+
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        metadataService = TestUtils.addSessionCleanupWrapper(metadataService);
+        new GraphBackedSearchIndexer(typeRegistry);
+        final AtlasTypesDef deptTypesDef = 
TestUtilsV2.defineDeptEmployeeTypes();
+        typeDefStore.createTypesDef(deptTypesDef);
+
+        final AtlasTypesDef hiveTypesDef = TestUtilsV2.defineHiveTypes();
+        typeDefStore.createTypesDef(hiveTypesDef);
+
+        // Define type for map value.
+        AtlasEntityDef mapValueDef = 
AtlasTypeUtil.createClassTypeDef("CompositeMapValue", "CompositeMapValue" + 
"_description", "1.0",
+            ImmutableSet.<String>of(),
+            AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string")
+        );
+
+        // Define type with map where the value is a composite class reference 
to MapValue.
+        AtlasEntityDef mapOwnerDef = 
AtlasTypeUtil.createClassTypeDef("CompositeMapOwner", 
"CompositeMapOwner_description",
+            ImmutableSet.<String>of(),
+            AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
+            AtlasTypeUtil.createOptionalAttrDef("map", "map<string,string>")
+        );
+
+        final AtlasTypesDef typesDef = 
AtlasTypeUtil.getTypesDef(ImmutableList.<AtlasEnumDef>of(),
+            ImmutableList.<AtlasStructDef>of(),
+            ImmutableList.<AtlasClassificationDef>of(),
+            ImmutableList.of(mapValueDef, mapOwnerDef));
+
+        typeDefStore.createTypesDef(typesDef);
+
+        compositeMapOwnerType = 
typeRegistry.getEntityTypeByName("CompositeMapOwner");
+        compositeMapValueType = 
typeRegistry.getEntityTypeByName("CompositeMapValue");
+    }
+
+    @BeforeTest
+    public void init() throws Exception {
+
+        final Class<? extends DeleteHandlerV1> deleteHandlerImpl = 
AtlasRepositoryConfiguration.getDeleteHandlerV1Impl();
+        final Constructor<? extends DeleteHandlerV1> 
deleteHandlerImplConstructor = 
deleteHandlerImpl.getConstructor(AtlasTypeRegistry.class);
+        DeleteHandlerV1 deleteHandler = 
deleteHandlerImplConstructor.newInstance(typeRegistry);
+
+        entityStore = new AtlasEntityStoreV1(deleteHandler, typeRegistry);
+        RequestContextV1.clear();
+
+    }
+
+    @AfterClass
+    public void clear() {
+        AtlasGraphProvider.cleanup();
+    }
+
+    abstract DeleteHandlerV1 getDeleteHandler(AtlasTypeRegistry typeRegistry);
+
+    @Test
+    public void testDeleteAndCreate() throws Exception {
+        init();
+        final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
+        EntityMutationResponse response = entityStore.createOrUpdate(new 
AtlasEntityStream(dbEntity));
+
+        init();
+        //delete entity should mark it as deleted
+        EntityMutationResponse deleteResponse = 
entityStore.deleteById(response.getFirstEntityCreated().getGuid());
+        AtlasEntityHeader dbEntityCreated = response.getFirstEntityCreated();
+        
assertEquals(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).get(0).getGuid(),
 dbEntityCreated.getGuid());
+
+        //get entity by unique attribute should throw EntityNotFoundException
+        try {
+            metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, 
"name", (String) response.getFirstEntityCreated().getAttribute("name"));
+            fail("Expected EntityNotFoundException");
+        } catch(EntityNotFoundException e) {
+            //expected
+        }
+
+        init();
+        //Create the same entity again, should create new entity
+        AtlasEntity newDBEntity = TestUtilsV2.createDBEntity((String) 
dbEntity.getAttribute(NAME));
+        EntityMutationResponse newCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(newDBEntity));
+        assertNotEquals(newCreationResponse.getFirstEntityCreated().getGuid(), 
response.getFirstEntityCreated().getGuid());
+
+        //TODO - Enable after GET is ready
+        //get by unique attribute should return the new entity
+        ITypedReferenceableInstance instance = 
metadataService.getEntityDefinitionReference(TestUtils.DATABASE_TYPE, "name", 
(String) dbEntity.getAttribute("name"));
+        assertEquals(instance.getId()._getId(), 
newCreationResponse.getFirstEntityCreated().getGuid());
+    }
+
+    @Test
+    public void testDeleteReference() throws Exception {
+        //Deleting column should update table
+        final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
+
+        init();
+        EntityMutationResponse dbCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
+
+        final AtlasEntity tableEntity = 
TestUtilsV2.createTableEntity(dbEntity);
+        final AtlasEntity columnEntity = 
TestUtilsV2.createColumnEntity(tableEntity);
+        tableEntity.setAttribute(COLUMNS_ATTR_NAME, 
Arrays.asList(columnEntity.getAtlasObjectId()));
+
+        AtlasEntity.AtlasEntityWithExtInfo input = new 
AtlasEntity.AtlasEntityWithExtInfo(tableEntity);
+        input.addReferredEntity(columnEntity);
+
+        init();
+        EntityMutationResponse tblCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(input));
+        final AtlasEntityHeader columnCreated = 
tblCreationResponse.getFirstCreatedEntityByTypeName(COLUMN_TYPE);
+        final AtlasEntityHeader tableCreated = 
tblCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE);
+
+        init();
+        EntityMutationResponse deletionResponse = 
entityStore.deleteById(columnCreated.getGuid());
+        assertEquals(deletionResponse.getDeletedEntities().size(), 1);
+        assertEquals(deletionResponse.getDeletedEntities().get(0).getGuid(), 
columnCreated.getGuid());
+        assertEquals(deletionResponse.getUpdatedEntities().size(), 1);
+        assertEquals(deletionResponse.getUpdatedEntities().get(0).getGuid(), 
tableCreated.getGuid());
+
+        assertEntityDeleted(columnCreated.getGuid());
+
+        //TODO - Fix after GET is ready
+//        ITypedReferenceableInstance tableInstance = 
repositoryService.getEntityDefinition(tableId);
+//        assertColumnForTestDeleteReference(tableInstance);
+
+        //Deleting table should update process
+        AtlasEntity process = TestUtilsV2.createProcessEntity(null, 
Arrays.asList(tableCreated.getAtlasObjectId()));
+        init();
+        final EntityMutationResponse processCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(process));
+
+        init();
+        entityStore.deleteById(tableCreated.getGuid());
+        assertEntityDeleted(tableCreated.getGuid());
+
+        assertTableForTestDeleteReference(tableCreated.getGuid());
+        
assertProcessForTestDeleteReference(processCreationResponse.getFirstEntityCreated());
+    }
+
+    @Test
+    public void testDeleteEntities() throws Exception {
+        // Create a table entity, with 3 composite column entities
+        init();
+        final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
+        EntityMutationResponse dbCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
+
+        final AtlasEntity tableEntity = 
TestUtilsV2.createTableEntity(dbEntity);
+        AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new 
AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
+
+        final AtlasEntity columnEntity1 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity1);
+        final AtlasEntity columnEntity2 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity2);
+        final AtlasEntity columnEntity3 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity3);
+
+        tableEntity.setAttribute(COLUMNS_ATTR_NAME, 
Arrays.asList(columnEntity1.getAtlasObjectId(), 
columnEntity2.getAtlasObjectId(), columnEntity3.getAtlasObjectId()));
+
+        init();
+
+        final EntityMutationResponse tblCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
+
+        final AtlasEntityHeader column1Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity1.getAttribute(NAME));
+        final AtlasEntityHeader column2Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity2.getAttribute(NAME));
+        final AtlasEntityHeader column3Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity3.getAttribute(NAME));
+
+        // Retrieve the table entities from the Repository, to get their guids 
and the composite column guids.
+        ITypedReferenceableInstance tableInstance = 
metadataService.getEntityDefinitionReference(TestUtils.TABLE_TYPE, NAME, 
(String) tableEntity.getAttribute(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();
+
+        init();
+
+        EntityMutationResponse deletionResponse = 
entityStore.deleteById(colId);
+        assertEquals(deletionResponse.getDeletedEntities().size(), 1);
+        assertEquals(deletionResponse.getDeletedEntities().get(0).getGuid(), 
colId);
+        assertEquals(deletionResponse.getUpdatedEntities().size(), 1);
+        assertEquals(deletionResponse.getUpdatedEntities().get(0).getGuid(), 
tableId);
+        assertEntityDeleted(colId);
+
+        tableInstance = 
metadataService.getEntityDefinitionReference(TestUtils.TABLE_TYPE, NAME, 
(String) tableEntity.getAttribute(NAME));
+        assertDeletedColumn(tableInstance);
+
+        assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
+            (List<ITypedReferenceableInstance>) tableInstance.get("columns"), 
colId);
+
+        //update by removing a column - col1
+        final AtlasEntity tableEntity1 = 
TestUtilsV2.createTableEntity(dbEntity, (String) 
tableEntity.getAttribute(NAME));
+
+        AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo1 = new 
AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity1);
+        final AtlasEntity columnEntity3New = 
TestUtilsV2.createColumnEntity(tableEntity1, (String) 
column3Created.getAttribute(NAME));
+        tableEntity1.setAttribute(COLUMNS_ATTR_NAME, 
Arrays.asList(columnEntity3New.getAtlasObjectId()));
+        entitiesInfo1.addReferredEntity(columnEntity3New);
+
+        init();
+        deletionResponse = entityStore.createOrUpdate(new 
AtlasEntityStream(entitiesInfo1));
+
+        //TODO - enable after fixing unique atribute resolver
+        assertEquals(deletionResponse.getDeletedEntities().size(), 1);
+        assertEquals(deletionResponse.getDeletedEntities().get(0).getGuid(), 
column2Created.getGuid());
+        assertEntityDeleted(colId);
+
+        // Delete the table entities.  The deletion should cascade to their 
composite columns.
+        tableInstance = 
metadataService.getEntityDefinitionReference(TestUtils.TABLE_TYPE, NAME, 
(String) tableEntity.getAttribute(NAME));
+
+        init();
+        EntityMutationResponse tblDeletionResponse = 
entityStore.deleteById(tableInstance.getId()._getId());
+        assertEquals(tblDeletionResponse.getDeletedEntities().size(), 2);
+
+        final AtlasEntityHeader tableDeleted = 
tblDeletionResponse.getFirstDeletedEntityByTypeName(TABLE_TYPE);
+        final AtlasEntityHeader colDeleted = 
tblDeletionResponse.getFirstDeletedEntityByTypeName(COLUMN_TYPE);
+
+        // Verify that deleteEntities() response has guids for tables and 
their composite columns.
+        
Assert.assertTrue(tableDeleted.getGuid().equals(tableInstance.getId()._getId()));
+        
Assert.assertTrue(colDeleted.getGuid().equals(column3Created.getGuid()));
+
+        // Verify that tables and their composite columns have been deleted 
from the graph Repository.
+        assertEntityDeleted(tableDeleted.getGuid());
+        assertEntityDeleted(colDeleted.getGuid());
+        assertTestDeleteEntities(tableInstance);
+
+    }
+
+    protected abstract void assertDeletedColumn(ITypedReferenceableInstance 
tableInstance) throws AtlasException;
+
+    protected abstract void 
assertTestDeleteEntities(ITypedReferenceableInstance tableInstance) throws 
Exception;
+
+    protected abstract void assertTableForTestDeleteReference(String tableId) 
throws Exception;
+
+    protected abstract void assertColumnForTestDeleteReference(AtlasEntity 
tableInstance)
+        throws AtlasException;
+
+    protected abstract void 
assertProcessForTestDeleteReference(AtlasEntityHeader processInstance) throws 
Exception;
+
+    protected abstract void assertEntityDeleted(String id) throws Exception;
+
+    String getFirstGuid(Map<String, AtlasEntity> entityMap) {
+        return entityMap.keySet().iterator().next();
+    }
+
+    @Test
+    public void testUpdateEntity_MultiplicityOneNonCompositeReference() throws 
Exception {
+        AtlasEntity.AtlasEntitiesWithExtInfo hrDept = 
TestUtilsV2.createDeptEg2();
+        init();
+
+        RequestContextV1.clear();
+        final EntityMutationResponse hrDeptCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(hrDept));
+        final AtlasEntityHeader deptCreated = 
hrDeptCreationResponse.getFirstUpdatedEntityByTypeName(DEPARTMENT_TYPE);
+        final AtlasEntityHeader maxEmployeeCreated = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE,
 NAME, "Max");
+        final AtlasEntityHeader johnEmployeeCreated = 
hrDeptCreationResponse.getUpdatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE,
 NAME, "John");
+        final AtlasEntityHeader janeEmployeeCreated = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.MANAGER_TYPE,
 NAME, "Jane");
+        final AtlasEntityHeader juliusEmployeeCreated = 
hrDeptCreationResponse.getUpdatedEntityByTypeNameAndAttribute(TestUtilsV2.MANAGER_TYPE,
 NAME, "Julius");
+
+//        ITypedReferenceableInstance hrDeptInstance = 
metadataService.getEntityDefinition(hrDeptCreationResponse.getFirstCreatedEntityByTypeName(DEPARTMENT_TYPE).getGuid());
+//        Map<String, String> nameGuidMap = 
getEmployeeNameGuidMap(hrDeptInstance);
+
+        ITypedReferenceableInstance max = 
metadataService.getEntityDefinition(maxEmployeeCreated.getGuid());
+        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);
+
+        AtlasEntity maxEmployee = getEmployeeByName(hrDept, "Max");
+        maxEmployee.setAttribute("mentor", 
johnEmployeeCreated.getAtlasObjectId());
+        maxEmployee.setAttribute("department", deptCreated.getAtlasObjectId());
+        maxEmployee.setAttribute("manager", 
janeEmployeeCreated.getAtlasObjectId());
+
+        init();
+        EntityMutationResponse entityResult = entityStore.createOrUpdate(new 
AtlasEntityStream(maxEmployee));
+
+        assertEquals(entityResult.getUpdatedEntities().size(), 1);
+        
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
+
+        // Verify the update was applied correctly - john should now be max's 
mentor.
+        max = metadataService.getEntityDefinition(maxGuid);
+        ITypedReferenceableInstance refTarget = (ITypedReferenceableInstance) 
max.get("mentor");
+        Assert.assertEquals(refTarget.getId()._getId(), 
johnEmployeeCreated.getGuid());
+
+        // 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.
+        maxEmployee.setAttribute("mentor", 
janeEmployeeCreated.getAtlasObjectId());
+        init();
+        entityResult = entityStore.createOrUpdate(new 
AtlasEntityStream(maxEmployee));
+        assertEquals(entityResult.getUpdatedEntities().size(), 1);
+        
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
+
+        // Verify the update was applied correctly - jane should now be max's 
mentor.
+        max = metadataService.getEntityDefinition(maxGuid);
+        refTarget = (ITypedReferenceableInstance) max.get("mentor");
+        Assert.assertEquals(refTarget.getId()._getId(), 
janeEmployeeCreated.getGuid());
+
+        // 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 = 
metadataService.getEntityDefinition(juliusEmployeeCreated.getGuid());
+        Id juliusGuid = julius.getId();
+
+        init();
+        maxEmployee.setAttribute("manager", 
juliusEmployeeCreated.getAtlasObjectId());
+        entityResult = entityStore.createOrUpdate(new 
AtlasEntityStream(maxEmployee));
+        //TODO ATLAS-499 should have updated julius' subordinates
+        assertEquals(entityResult.getUpdatedEntities().size(), 2);
+        
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
+        
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(janeEmployeeCreated.getGuid()));
+
+        // Verify the update was applied correctly - julius should now be 
max's manager.
+        max = metadataService.getEntityDefinition(maxGuid);
+        refTarget = (ITypedReferenceableInstance) max.get("manager");
+        Assert.assertEquals(refTarget.getId()._getId(), juliusGuid._getId());
+
+        
assertTestUpdateEntity_MultiplicityOneNonCompositeReference(janeEmployeeCreated.getGuid());
+    }
+
+    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;
+    }
+
+
+    private AtlasEntity getEmployeeByName(AtlasEntity.AtlasEntitiesWithExtInfo 
hrDept, String name) {
+        for (AtlasEntity entity : hrDept.getEntities()) {
+            if ( name.equals(entity.getAttribute(NAME))) {
+                return entity;
+            }
+        }
+        return null;
+    }
+//
+    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 {
+        AtlasEntity.AtlasEntitiesWithExtInfo hrDept = 
TestUtilsV2.createDeptEg2();
+        init();
+        final EntityMutationResponse hrDeptCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(hrDept));
+
+        final AtlasEntityHeader deptCreated = 
hrDeptCreationResponse.getFirstCreatedEntityByTypeName(DEPARTMENT_TYPE);
+        final AtlasEntityHeader maxEmployee = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE,
 NAME, "Max");
+        final AtlasEntityHeader johnEmployee = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE,
 NAME, "John");
+        final AtlasEntityHeader janeEmployee = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.MANAGER_TYPE,
 NAME, "Jane");
+        final AtlasEntityHeader juliusEmployee = 
hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.MANAGER_TYPE,
 NAME, "Julius");
+
+        ITypedReferenceableInstance hrDeptInstance = 
metadataService.getEntityDefinition(deptCreated.getGuid());
+        Map<String, String> nameGuidMap = 
getEmployeeNameGuidMap(hrDeptInstance);
+
+        // Verify that Max is one of Jane's subordinates.
+        ITypedReferenceableInstance jane = 
metadataService.getEntityDefinition(janeEmployee.getGuid());
+        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(maxEmployee.getGuid()));
+
+        init();
+        EntityMutationResponse entityResult = 
entityStore.deleteById(maxEmployee.getGuid());
+        ITypedReferenceableInstance john = 
metadataService.getEntityDefinitionReference(TestUtilsV2.EMPLOYEE_TYPE, NAME, 
"John");
+
+        assertEquals(entityResult.getDeletedEntities().size(), 1);
+        assertEquals(entityResult.getDeletedEntities().get(0).getGuid(), 
maxEmployee.getGuid());
+        assertEquals(entityResult.getUpdatedEntities().size(), 3);
+
+        assertEquals(extractGuids(entityResult.getUpdatedEntities()), 
Arrays.asList(janeEmployee.getGuid(), deptCreated.getGuid(), 
johnEmployee.getGuid()));
+        assertEntityDeleted(maxEmployee.getGuid());
+
+        assertMaxForTestDisconnectBidirectionalReferences(nameGuidMap);
+
+        // Now delete jane - this should disconnect the manager reference from 
her
+        // subordinate.
+        init();
+        entityResult = entityStore.deleteById(janeEmployee.getGuid());
+        assertEquals(entityResult.getDeletedEntities().size(), 1);
+        assertEquals(entityResult.getDeletedEntities().get(0).getGuid(), 
janeEmployee.getGuid());
+        assertEquals(entityResult.getUpdatedEntities().size(), 2);
+        assertEquals(extractGuids(entityResult.getUpdatedEntities()), 
Arrays.asList(deptCreated.getGuid(), johnEmployee.getGuid()));
+
+        assertEntityDeleted(janeEmployee.getGuid());
+
+        john = 
metadataService.getEntityDefinitionReference(TestUtilsV2.EMPLOYEE_TYPE, NAME, 
"John");
+        assertJohnForTestDisconnectBidirectionalReferences(john, 
janeEmployee.getGuid());
+    }
+
+    protected List<String> extractGuids(final List<AtlasEntityHeader> 
updatedEntities) {
+        List<String> guids = new ArrayList<>();
+        for (AtlasEntityHeader header : updatedEntities ) {
+            guids.add(header.getGuid());
+        }
+        return guids;
+    }
+
+    protected abstract void 
assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance 
john,
+        String janeGuid) throws Exception;
+
+    protected abstract void 
assertMaxForTestDisconnectBidirectionalReferences(Map<String, String> 
nameGuidMap)
+        throws Exception;
+
+    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.
+        AtlasStructDef.AtlasAttributeDef[] structTargetAttributes = new 
AtlasStructDef.AtlasAttributeDef[]{
+            new AtlasStructDef.AtlasAttributeDef("attr1", "string",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList())};
+
+        AtlasEntityDef structTargetDef =
+            new AtlasEntityDef("StructTarget", "StructTarget_description", 
"1.0",
+                Arrays.asList(structTargetAttributes), 
Collections.<String>emptySet());
+
+
+        AtlasStructDef.AtlasAttributeDef[] traitTargetAttributes = new 
AtlasStructDef.AtlasAttributeDef[]{
+            new AtlasStructDef.AtlasAttributeDef("attr1", "string",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList())};
+
+        AtlasEntityDef traitTargetDef =
+            new AtlasEntityDef("TraitTarget", "TraitTarget_description", "1.0",
+                Arrays.asList(traitTargetAttributes), 
Collections.<String>emptySet());
+
+        AtlasStructDef.AtlasAttributeDef[] structContainerAttributes = new 
AtlasStructDef.AtlasAttributeDef[]{
+            new AtlasStructDef.AtlasAttributeDef("struct", "TestStruct",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList())};
+
+        AtlasEntityDef structContainerDef =
+            new AtlasEntityDef("StructContainer", 
"StructContainer_description", "1.0",
+                Arrays.asList(structContainerAttributes), 
Collections.<String>emptySet());
+
+        // Define struct and trait types which have a unidirectional array 
reference
+        // to a class type.
+        AtlasStructDef.AtlasAttributeDef[] structDefAttributes = new 
AtlasStructDef.AtlasAttributeDef[] {
+            new AtlasStructDef.AtlasAttributeDef("target", 
"array<StructTarget>",
+            true,
+            AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+            false, false,
+            Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
+
+            new AtlasStructDef.AtlasAttributeDef("nestedStructs", 
"array<NestedStruct>",
+            true,
+            AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+            false, false,
+            Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()) };
+
+        AtlasStructDef structDef = new AtlasStructDef("TestStruct", 
"TestStruct_desc", "1.0", Arrays.asList(structDefAttributes));
+
+
+        // Define struct and trait types which have a unidirectional array 
reference
+        // to a class type.
+        AtlasStructDef.AtlasAttributeDef[] nestedStructDefAttributes = new 
AtlasStructDef.AtlasAttributeDef[] {
+            new AtlasStructDef.AtlasAttributeDef("attr1", "string",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
+
+            new AtlasStructDef.AtlasAttributeDef("target", 
"array<TraitTarget>",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()) };
+
+        AtlasStructDef nestedStructDef = new AtlasStructDef("NestedStruct", 
"NestedStruct_desc", "1.0", Arrays.asList(nestedStructDefAttributes));
+
+        AtlasStructDef.AtlasAttributeDef[] traitDefAttributes = new 
AtlasStructDef.AtlasAttributeDef[] {
+            new AtlasStructDef.AtlasAttributeDef("target", 
"array<TraitTarget>",
+                true,
+                AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
+                false, false,
+                Collections.<AtlasStructDef.AtlasConstraintDef>emptyList())
+        };
+
+        AtlasClassificationDef traitDef = new 
AtlasClassificationDef("TestTrait", "TestTrait_desc", "1.0", 
Arrays.asList(traitDefAttributes));
+
+        AtlasTypesDef typesDef = 
AtlasTypeUtil.getTypesDef(ImmutableList.<AtlasEnumDef>of(),
+            ImmutableList.<AtlasStructDef>of(structDef, nestedStructDef),
+            ImmutableList.<AtlasClassificationDef>of(traitDef),
+            ImmutableList.<AtlasEntityDef>of(structTargetDef, traitTargetDef, 
structContainerDef));
+
+        typeDefStore.createTypesDef(typesDef);
+
+        // Create instances of class, struct, and trait types.
+        final AtlasEntity structTargetEntity = new AtlasEntity("StructTarget");
+        final AtlasEntity traitTargetEntity = new AtlasEntity("TraitTarget");
+        final AtlasEntity structContainerEntity = new 
AtlasEntity("StructContainer");
+        AtlasStruct structInstance = new AtlasStruct("TestStruct");
+        AtlasStruct nestedStructInstance = new AtlasStruct("NestedStruct");
+        Struct traitInstance = new Struct("TestTrait");
+        structContainerEntity.setAttribute("struct", structInstance);
+        structInstance.setAttribute("target", 
ImmutableList.of(structTargetEntity.getAtlasObjectId()));
+        structInstance.setAttribute("nestedStructs", 
ImmutableList.of(nestedStructInstance));
+
+        AtlasEntity.AtlasEntitiesWithExtInfo structCreationObj = new 
AtlasEntity.AtlasEntitiesWithExtInfo();
+        structCreationObj.addEntity(structContainerEntity);
+        structCreationObj.addEntity(traitTargetEntity);
+        structCreationObj.addReferredEntity(structTargetEntity);
+
+        init();
+
+        AtlasEntityStream entityStream = new 
AtlasEntityStream(structCreationObj);
+
+        EntityMutationResponse response = 
entityStore.createOrUpdate(entityStream);
+        Assert.assertEquals(response.getCreatedEntities().size(), 3);
+
+        final List<String> structTarget = 
metadataService.getEntityList("StructTarget");
+        Assert.assertEquals(structTarget.size(), 1);
+        final String structTargetGuid = structTarget.get(0);
+
+        final List<String> traitTarget = 
metadataService.getEntityList("TraitTarget");
+        Assert.assertEquals(traitTarget.size(), 1);
+        final String traitTargetGuid = traitTarget.get(0);
+
+        final List<String> structContainerTarget = 
metadataService.getEntityList("StructContainer");
+        Assert.assertEquals(structContainerTarget.size(), 1);
+        String structContainerGuid = structContainerTarget.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);
+        metadataService.addTrait(structContainerGuid, convertedTrait);
+
+        // Verify that the unidirectional references from the struct and trait 
instances
+        // are pointing at the target entities.
+        final ITypedReferenceableInstance structContainerConvertedEntity = 
metadataService.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);
+
+        init();
+        // Delete the entities that are targets of the struct and trait 
instances.
+        EntityMutationResponse entityResult = entityStore.deleteByIds(new 
ArrayList<String>() {{
+            add(structTargetGuid);
+            add(traitTargetGuid);
+        }});
+        Assert.assertEquals(entityResult.getDeletedEntities().size(), 2);
+        
Assert.assertTrue(extractGuids(entityResult.getDeletedEntities()).containsAll(Arrays.asList(structTargetGuid,
 traitTargetGuid)));
+        assertEntityDeleted(structTargetGuid);
+        assertEntityDeleted(traitTargetGuid);
+
+        
assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(structContainerGuid);
+
+        init();
+        // Delete the entity which contains nested structs and has the 
TestTrait trait.
+        entityResult = entityStore.deleteById(structContainerGuid);
+        Assert.assertEquals(entityResult.getDeletedEntities().size(), 1);
+        
Assert.assertTrue(extractGuids(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"));
+    }
+
+    @Test
+    public void testDeleteByUniqueAttribute() throws Exception {
+        // Create a table entity, with 3 composite column entities
+        init();
+        final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
+        EntityMutationResponse dbCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
+
+        final AtlasEntity tableEntity = 
TestUtilsV2.createTableEntity(dbEntity);
+        AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new 
AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
+
+        final AtlasEntity columnEntity1 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity1);
+        final AtlasEntity columnEntity2 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity2);
+        final AtlasEntity columnEntity3 = 
TestUtilsV2.createColumnEntity(tableEntity);
+        entitiesInfo.addReferredEntity(columnEntity3);
+
+        tableEntity.setAttribute(COLUMNS_ATTR_NAME, 
Arrays.asList(columnEntity1.getAtlasObjectId(), 
columnEntity2.getAtlasObjectId(), columnEntity3.getAtlasObjectId()));
+
+        init();
+
+        final EntityMutationResponse tblCreationResponse = 
entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
+
+        final AtlasEntityHeader column1Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity1.getAttribute(NAME));
+        final AtlasEntityHeader column2Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity2.getAttribute(NAME));
+        final AtlasEntityHeader column3Created = 
tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, 
(String) columnEntity3.getAttribute(NAME));
+
+        // Retrieve the table entities from the Repository, to get their guids 
and the composite column guids.
+        ITypedReferenceableInstance tableInstance = 
metadataService.getEntityDefinitionReference(TestUtils.TABLE_TYPE, NAME, 
(String) tableEntity.getAttribute(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();
+
+        init();
+
+        Map<String, Object> uniqueAttrs = new HashMap<>();
+        uniqueAttrs.put(NAME, column1Created.getAttribute(NAME));
+
+        AtlasEntityType columnType = 
typeRegistry.getEntityTypeByName(COLUMN_TYPE);
+        EntityMutationResponse deletionResponse = 
entityStore.deleteByUniqueAttributes(columnType, uniqueAttrs);
+        assertEquals(deletionResponse.getDeletedEntities().size(), 1);
+        assertEquals(deletionResponse.getDeletedEntities().get(0).getGuid(), 
colId);
+        assertEquals(deletionResponse.getUpdatedEntities().size(), 1);
+        assertEquals(deletionResponse.getUpdatedEntities().get(0).getGuid(), 
tableId);
+        assertEntityDeleted(colId);
+
+        tableInstance = 
metadataService.getEntityDefinitionReference(TestUtils.TABLE_TYPE, NAME, 
(String) tableEntity.getAttribute(NAME));
+        assertDeletedColumn(tableInstance);
+    }
+
+    protected abstract void 
assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(
+        String structContainerGuid) throws Exception;
+
+    protected abstract void assertVerticesDeleted(List<AtlasVertex> vertices);
+
+    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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aa67f8ae/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
----------------------------------------------------------------------
diff --git 
a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
index bb7de4a..e812ca6 100644
--- 
a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
+++ 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java
@@ -119,13 +119,11 @@ public class AtlasEntityStoreV1Test {
     @AfterClass
     public void clear() {
         AtlasGraphProvider.cleanup();
-        TestUtils.resetRequestContext();
     }
 
     @BeforeTest
     public void init() throws Exception {
         entityStore = new AtlasEntityStoreV1(deleteHandler, typeRegistry);
-
         RequestContextV1.clear();
     }
 
@@ -138,7 +136,7 @@ public class AtlasEntityStoreV1Test {
         AtlasEntityHeader dept1 = 
response.getFirstCreatedEntityByTypeName(TestUtilsV2.DEPARTMENT_TYPE);
         validateEntity(deptEntity, getEntityFromStore(dept1), 
deptEntity.getEntities().get(0));
 
-        final Map<EntityOperation, List<AtlasEntityHeader>> entitiesMutated = 
response.getEntitiesMutated();
+        final Map<EntityOperation, List<AtlasEntityHeader>> entitiesMutated = 
response.getMutatedEntities();
         List<AtlasEntityHeader> entitiesCreated = 
entitiesMutated.get(EntityOperation.CREATE);
 
         Assert.assertTrue(entitiesCreated.size() >= 
deptEntity.getEntities().size());

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aa67f8ae/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1Test.java
----------------------------------------------------------------------
diff --git 
a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1Test.java
 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1Test.java
new file mode 100644
index 0000000..987951e
--- /dev/null
+++ 
b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1Test.java
@@ -0,0 +1,198 @@
+/**
+ * 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.repository.store.graph.v1;
+
+
+import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.services.MetadataService;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.typesystem.IStruct;
+import org.apache.atlas.typesystem.ITypedReferenceableInstance;
+import org.apache.atlas.typesystem.ITypedStruct;
+import org.apache.atlas.typesystem.persistence.Id;
+import org.testng.Assert;
+
+import javax.inject.Inject;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
+import static org.apache.atlas.TestUtils.NAME;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class SoftDeleteHandlerV1Test extends AtlasDeleteHandlerV1Test {
+
+    @Inject
+    MetadataService metadataService;
+
+    @Override
+    DeleteHandlerV1 getDeleteHandler(final AtlasTypeRegistry typeRegistry) {
+        return new SoftDeleteHandlerV1(typeRegistry);
+    }
+
+    @Override
+    protected void assertDeletedColumn(final ITypedReferenceableInstance 
tableInstance) throws AtlasException {
+
+    }
+
+    @Override
+    protected void assertTestDeleteEntities(final ITypedReferenceableInstance 
tableInstance) throws Exception {
+
+    }
+
+    @Override
+    protected void assertTableForTestDeleteReference(final String tableId) 
throws Exception {
+
+        //TODO - Fix after GET is ready
+        ITypedReferenceableInstance table = 
metadataService.getEntityDefinition(tableId);
+        assertNotNull(table.get(NAME));
+        assertNotNull(table.get("description"));
+        assertNotNull(table.get("type"));
+        assertNotNull(table.get("tableType"));
+        assertNotNull(table.get("created"));
+
+        Id dbId = (Id) table.get("database");
+        assertNotNull(dbId);
+
+        ITypedReferenceableInstance db = 
metadataService.getEntityDefinition(dbId.getId()._getId());
+        assertNotNull(db);
+        assertEquals(db.getId().getState(), Id.EntityState.ACTIVE);
+
+    }
+
+    @Override
+    protected void assertColumnForTestDeleteReference(final AtlasEntity 
tableInstance) throws AtlasException {
+
+        List<AtlasObjectId> columns = (List<AtlasObjectId>) 
tableInstance.getAttribute(COLUMNS_ATTR_NAME);
+        assertEquals(columns.size(), 1);
+
+        //TODO - Enable after GET is ready
+        ITypedReferenceableInstance colInst = 
metadataService.getEntityDefinition(columns.get(0).getGuid());
+        assertEquals(colInst.getId().getState(), Id.EntityState.DELETED);
+    }
+
+    @Override
+    protected void assertProcessForTestDeleteReference(final AtlasEntityHeader 
processInstance) throws Exception {
+        //
+        ITypedReferenceableInstance process = 
metadataService.getEntityDefinition(processInstance.getGuid());
+        List<ITypedReferenceableInstance> outputs =
+            (List<ITypedReferenceableInstance>) 
process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
+        List<ITypedReferenceableInstance> expectedOutputs =
+            (List<ITypedReferenceableInstance>) 
process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
+        assertEquals(outputs.size(), expectedOutputs.size());
+
+    }
+
+    @Override
+    protected void assertEntityDeleted(final String id) throws Exception {
+//        ITypedReferenceableInstance entity = 
metadataService.getEntityDefinition(id);
+//        assertEquals(entity.getId().getState(), Id.EntityState.DELETED);
+        final AtlasEntity.AtlasEntityWithExtInfo byId = 
entityStore.getById(id);
+        assertEquals(byId.getEntity().getStatus(), AtlasEntity.Status.DELETED);
+    }
+
+    @Override
+    protected void 
assertTestUpdateEntity_MultiplicityOneNonCompositeReference(final String 
janeGuid) throws Exception {
+        // Verify Jane's subordinates reference cardinality is still 2.
+        ITypedReferenceableInstance jane = 
metadataService.getEntityDefinition(janeGuid);
+        List<ITypedReferenceableInstance> subordinates = 
(List<ITypedReferenceableInstance>) jane.get("subordinates");
+        Assert.assertEquals(subordinates.size(), 2);
+    }
+
+    @Override
+    protected void assertJohnForTestDisconnectBidirectionalReferences(final 
ITypedReferenceableInstance john, final String janeGuid) throws Exception {
+        Id mgr = (Id) john.get("manager");
+        assertNotNull(mgr);
+        assertEquals(mgr._getId(), janeGuid);
+        assertEquals(mgr.getState(), Id.EntityState.DELETED);
+    }
+
+    @Override
+    protected void assertMaxForTestDisconnectBidirectionalReferences(final 
Map<String, String> nameGuidMap) throws Exception {
+
+        // Verify that the Department.employees reference to the deleted 
employee
+        // was disconnected.
+        ITypedReferenceableInstance hrDept = 
metadataService.getEntityDefinition(nameGuidMap.get("hr"));
+        List<ITypedReferenceableInstance> employees = 
(List<ITypedReferenceableInstance>) hrDept.get("employees");
+        Assert.assertEquals(employees.size(), 4);
+        String maxGuid = nameGuidMap.get("Max");
+        for (ITypedReferenceableInstance employee : employees) {
+            if (employee.getId()._getId().equals(maxGuid)) {
+                assertEquals(employee.getId().getState(), 
Id.EntityState.DELETED);
+            }
+        }
+
+        // Verify that the Manager.subordinates still references deleted 
employee
+        ITypedReferenceableInstance jane = 
metadataService.getEntityDefinition(nameGuidMap.get("Jane"));
+        List<ITypedReferenceableInstance> subordinates = 
(List<ITypedReferenceableInstance>) jane.get("subordinates");
+        assertEquals(subordinates.size(), 2);
+        for (ITypedReferenceableInstance subordinate : subordinates) {
+            if (subordinate.getId()._getId().equals(maxGuid)) {
+                assertEquals(subordinate.getId().getState(), 
Id.EntityState.DELETED);
+            }
+        }
+
+        // Verify that max's Person.mentor unidirectional reference to john 
was disconnected.
+        ITypedReferenceableInstance john = 
metadataService.getEntityDefinition(nameGuidMap.get("John"));
+        Id mentor = (Id) john.get("mentor");
+        assertEquals(mentor._getId(), maxGuid);
+        assertEquals(mentor.getState(), Id.EntityState.DELETED);
+
+    }
+
+    @Override
+    protected void 
assertTestDisconnectUnidirectionalArrayReferenceFromClassType(final 
List<ITypedReferenceableInstance> columns, final String columnGuid) {
+        Assert.assertEquals(columns.size(), 3);
+        for (ITypedReferenceableInstance column : columns) {
+            if (column.getId()._getId().equals(columnGuid)) {
+                assertEquals(column.getId().getState(), 
Id.EntityState.DELETED);
+            } else {
+                assertEquals(column.getId().getState(), Id.EntityState.ACTIVE);
+            }
+        }
+    }
+
+    @Override
+    protected void 
assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(final 
String structContainerGuid) throws Exception {
+        // Verify that the unidirectional references from the struct and trait 
instances
+        // to the deleted entities were not disconnected.
+        ITypedReferenceableInstance structContainerConvertedEntity =
+            metadataService.getEntityDefinition(structContainerGuid);
+        ITypedStruct struct = (ITypedStruct) 
structContainerConvertedEntity.get("struct");
+        assertNotNull(struct.get("target"));
+        IStruct trait = structContainerConvertedEntity.getTrait("TestTrait");
+        assertNotNull(trait);
+        assertNotNull(trait.get("target"));
+
+    }
+
+    @Override
+    protected void assertVerticesDeleted(List<AtlasVertex> vertices) {
+        for (AtlasVertex vertex : vertices) {
+            assertEquals(GraphHelper.getSingleValuedProperty(vertex, 
Constants.STATE_PROPERTY_KEY, String.class), Id.EntityState.DELETED.name());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/aa67f8ae/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
----------------------------------------------------------------------
diff --git a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java 
b/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
index 23eb4ce..bf73174 100644
--- a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
+++ b/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
@@ -115,8 +115,8 @@ public class RequestContextV1 {
         return requestTime;
     }
     
-    public boolean isDeletedEntity(String entityGuid) {
-        return deletedEntityIds.contains(entityGuid);
+    public boolean isDeletedEntity(AtlasObjectId entityId) {
+        return deletedEntityIds.contains(entityId);
     }
 
     public static Metrics getMetrics() {

Reply via email to