You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sh...@apache.org on 2016/05/25 18:34:35 UTC

[2/3] incubator-atlas git commit: ATLAS-716 Entity update/delete notifications (shwethags)

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/repository/graph/GraphToTypedInstanceMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphToTypedInstanceMapper.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphToTypedInstanceMapper.java
index df28ab3..e240fb6 100644
--- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphToTypedInstanceMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphToTypedInstanceMapper.java
@@ -68,9 +68,9 @@ public final class GraphToTypedInstanceMapper {
         LOG.debug("Mapping graph root vertex {} to typed instance for guid {}", instanceVertex, guid);
         String typeName = instanceVertex.getProperty(Constants.ENTITY_TYPE_PROPERTY_KEY);
         List<String> traits = GraphHelper.getTraitNames(instanceVertex);
+        String state = GraphHelper.getStateAsString(instanceVertex);
 
-        Id id = new Id(guid, instanceVertex.<Integer>getProperty(Constants.VERSION_PROPERTY_KEY), typeName,
-                instanceVertex.<String>getProperty(Constants.STATE_PROPERTY_KEY));
+        Id id = new Id(guid, instanceVertex.<Integer>getProperty(Constants.VERSION_PROPERTY_KEY), typeName, state);
         LOG.debug("Created id {} for instance type {}", id, typeName);
 
         ClassType classType = typeSystem.getDataType(ClassType.class, typeName);
@@ -161,9 +161,9 @@ public final class GraphToTypedInstanceMapper {
 
         Edge edge;
         if (edgeId == null) {
-            edge = GraphHelper.getEdgeForLabel(instanceVertex, relationshipLabel);;
+            edge = GraphHelper.getEdgeForLabel(instanceVertex, relationshipLabel);
         } else {
-            edge = graphHelper.getEdgeById(edgeId);
+            edge = graphHelper.getEdgeByEdgeId(instanceVertex, relationshipLabel, edgeId);
         }
 
         if (edge != null) {
@@ -175,9 +175,10 @@ public final class GraphToTypedInstanceMapper {
                 LOG.debug("Found composite, mapping vertex to instance");
                 return mapGraphToTypedInstance(guid, referenceVertex);
             } else {
+                String state = GraphHelper.getStateAsString(referenceVertex);
                 Id referenceId =
                         new Id(guid, referenceVertex.<Integer>getProperty(Constants.VERSION_PROPERTY_KEY),
-                                dataType.getName());
+                                dataType.getName(), state);
                 LOG.debug("Found non-composite, adding id {} ", referenceId);
                 return referenceId;
             }
@@ -271,7 +272,7 @@ public final class GraphToTypedInstanceMapper {
         if (edgeId == null) {
             edge = GraphHelper.getEdgeForLabel(instanceVertex, relationshipLabel);
         } else {
-            edge = graphHelper.getEdgeById(edgeId);
+            edge = graphHelper.getEdgeByEdgeId(instanceVertex, relationshipLabel, edgeId);
         }
 
         if (edge != null) {

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/repository/graph/HardDeleteHandler.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/HardDeleteHandler.java b/repository/src/main/java/org/apache/atlas/repository/graph/HardDeleteHandler.java
index f8bbf73..3636791 100644
--- a/repository/src/main/java/org/apache/atlas/repository/graph/HardDeleteHandler.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/HardDeleteHandler.java
@@ -26,20 +26,18 @@ import org.apache.atlas.typesystem.types.TypeSystem;
 
 public class HardDeleteHandler extends DeleteHandler {
 
-    private static final GraphHelper graphHelper = GraphHelper.getInstance();
-
     @Inject
     public HardDeleteHandler(TypeSystem typeSystem) {
-        super(typeSystem, true);
+        super(typeSystem, true, false);
     }
 
     @Override
-    protected void _deleteVertex(Vertex instanceVertex) {
+    protected void _deleteVertex(Vertex instanceVertex, boolean force) {
         graphHelper.removeVertex(instanceVertex);
     }
 
     @Override
-    protected void deleteEdge(Edge edge) throws AtlasException {
+    protected void deleteEdge(Edge edge, boolean force) throws AtlasException {
         graphHelper.removeEdge(edge);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/repository/graph/SoftDeleteHandler.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/SoftDeleteHandler.java b/repository/src/main/java/org/apache/atlas/repository/graph/SoftDeleteHandler.java
index aa78582..25aa7c5 100644
--- a/repository/src/main/java/org/apache/atlas/repository/graph/SoftDeleteHandler.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/SoftDeleteHandler.java
@@ -32,24 +32,34 @@ import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY;
 public class SoftDeleteHandler extends DeleteHandler {
     @Inject
     public SoftDeleteHandler(TypeSystem typeSystem) {
-        super(typeSystem, false);
+        super(typeSystem, false, true);
     }
 
     @Override
-    protected void _deleteVertex(Vertex instanceVertex) {
-        Id.EntityState state = Id.EntityState.valueOf((String) instanceVertex.getProperty(STATE_PROPERTY_KEY));
-        if (state != Id.EntityState.DELETED) {
-            GraphHelper.setProperty(instanceVertex, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
-            GraphHelper.setProperty(instanceVertex, MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
+    protected void _deleteVertex(Vertex instanceVertex, boolean force) {
+        if (force) {
+            graphHelper.removeVertex(instanceVertex);
+        } else {
+            Id.EntityState state = GraphHelper.getState(instanceVertex);
+            if (state != Id.EntityState.DELETED) {
+                GraphHelper.setProperty(instanceVertex, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
+                GraphHelper.setProperty(instanceVertex, MODIFICATION_TIMESTAMP_PROPERTY_KEY,
+                        RequestContext.get().getRequestTime());
+            }
         }
     }
 
     @Override
-    protected void deleteEdge(Edge edge) throws AtlasException {
-        Id.EntityState state = Id.EntityState.valueOf((String) edge.getProperty(STATE_PROPERTY_KEY));
-        if (state != Id.EntityState.DELETED) {
-            GraphHelper.setProperty(edge, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
-            GraphHelper.setProperty(edge, MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
+    protected void deleteEdge(Edge edge, boolean force) throws AtlasException {
+        if (force) {
+            graphHelper.removeEdge(edge);
+        } else {
+            Id.EntityState state = GraphHelper.getState(edge);
+            if (state != Id.EntityState.DELETED) {
+                GraphHelper.setProperty(edge, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
+                GraphHelper
+                        .setProperty(edge, MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
index a017536..4c1f559 100644
--- a/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/TypedInstanceToGraphMapper.java
@@ -101,15 +101,15 @@ public final class TypedInstanceToGraphMapper {
             case CREATE:
                 List<String> ids = addOrUpdateAttributesAndTraits(operation, entitiesToCreate);
                 addFullTextProperty(entitiesToCreate, fulltextMapper);
-                requestContext.recordCreatedEntities(ids);
+                requestContext.recordEntityCreate(ids);
                 break;
 
             case UPDATE_FULL:
             case UPDATE_PARTIAL:
                 ids = addOrUpdateAttributesAndTraits(Operation.CREATE, entitiesToCreate);
-                requestContext.recordCreatedEntities(ids);
+                requestContext.recordEntityCreate(ids);
                 ids = addOrUpdateAttributesAndTraits(operation, entitiesToUpdate);
-                requestContext.recordUpdatedEntities(ids);
+                requestContext.recordEntityUpdate(ids);
 
                 addFullTextProperty(entitiesToCreate, fulltextMapper);
                 addFullTextProperty(entitiesToUpdate, fulltextMapper);
@@ -218,8 +218,8 @@ public final class TypedInstanceToGraphMapper {
                         attrValue, currentEdge, edgeLabel, operation);
 
                 if (currentEdge != null && !currentEdge.getId().toString().equals(newEdgeId)) {
-                    deleteHandler.deleteReference(currentEdge, attributeInfo.dataType().getTypeCategory(),
-                            attributeInfo.isComposite);
+                    deleteHandler.deleteEdgeReference(currentEdge, attributeInfo.dataType().getTypeCategory(),
+                            attributeInfo.isComposite, true);
                 }
                 break;
 
@@ -326,7 +326,7 @@ public final class TypedInstanceToGraphMapper {
         String propertyName = GraphHelper.getQualifiedFieldName(typedInstance, attributeInfo);
         List<String> currentElements = instanceVertex.getProperty(propertyName);
         IDataType elementType = ((DataTypes.ArrayType) attributeInfo.dataType()).getElemType();
-        List<String> newElementsCreated = new ArrayList<>();
+        List<Object> newElementsCreated = new ArrayList<>();
 
         if (!newAttributeEmpty) {
             if (newElements != null && !newElements.isEmpty()) {
@@ -336,75 +336,53 @@ public final class TypedInstanceToGraphMapper {
                             currentElements.get(index) : null;
                     LOG.debug("Adding/updating element at position {}, current element {}, new element {}", index,
                             currentElement, newElements.get(index));
-                    String newEntry = addOrUpdateCollectionEntry(instanceVertex, attributeInfo, elementType,
+                    Object newEntry = addOrUpdateCollectionEntry(instanceVertex, attributeInfo, elementType,
                             newElements.get(index), currentElement, propertyName, operation);
                     newElementsCreated.add(newEntry);
                 }
             }
         }
 
+        List<String> additionalEdges = removeUnusedEntries(instanceVertex, propertyName, currentElements,
+                newElementsCreated, elementType, attributeInfo);
+        newElementsCreated.addAll(additionalEdges);
+
         // for dereference on way out
         GraphHelper.setProperty(instanceVertex, propertyName, newElementsCreated);
-
-        removeUnusedEntries(currentElements, newElementsCreated, elementType, attributeInfo);
     }
 
-    private void removeUnusedEntries(List<String> currentEntries, List<String> newEntries, IDataType entryType,
-                                     AttributeInfo attributeInfo) throws AtlasException {
-        if (currentEntries == null || currentEntries.isEmpty()) {
-            return;
-        }
-
-        LOG.debug("Removing unused entries from the old collection");
-        if (entryType.getTypeCategory() == DataTypes.TypeCategory.STRUCT
-                || entryType.getTypeCategory() == DataTypes.TypeCategory.CLASS) {
-
-            //Get map of edge id to edge
-            Map<String, Edge> edgeMap = new HashMap<>();
-            getEdges(currentEntries, edgeMap);
-            getEdges(newEntries, edgeMap);
-
-            //Get final set of in vertices
-            Set<String> newInVertices = new HashSet<>();
-            for (String edgeId : newEntries) {
-                Vertex inVertex = edgeMap.get(edgeId).getVertex(Direction.IN);
-                newInVertices.add(inVertex.getId().toString());
-            }
-
-            //Remove the edges for (current edges - new edges)
-            List<String> cloneElements = new ArrayList<>(currentEntries);
-            cloneElements.removeAll(newEntries);
-            LOG.debug("Removing unused entries from the old collection - {}", cloneElements);
-
-            if (!cloneElements.isEmpty()) {
-                for (String edgeIdForDelete : cloneElements) {
-                    Edge edge = edgeMap.get(edgeIdForDelete);
-                    Vertex inVertex = edge.getVertex(Direction.IN);
-                    if (newInVertices.contains(inVertex.getId().toString())) {
-                        //If the edge.inVertex is in the new set of in vertices, just delete the edge
-                        deleteHandler.deleteEdge(edge, true);
-                    } else {
-                        //else delete the edge + vertex
-                        deleteHandler.deleteReference(edge, entryType.getTypeCategory(), attributeInfo.isComposite);
+    //Removes unused edges from the old collection, compared to the new collection
+    private List<String> removeUnusedEntries(Vertex instanceVertex, String edgeLabel,
+                                             Collection<String> currentEntries,
+                                             Collection<Object> newEntries,
+                                             IDataType entryType, AttributeInfo attributeInfo) throws AtlasException {
+        if (currentEntries != null && !currentEntries.isEmpty()) {
+            LOG.debug("Removing unused entries from the old collection");
+            if (entryType.getTypeCategory() == DataTypes.TypeCategory.STRUCT
+                    || entryType.getTypeCategory() == DataTypes.TypeCategory.CLASS) {
+
+                //Remove the edges for (current edges - new edges)
+                List<String> cloneElements = new ArrayList<>(currentEntries);
+                cloneElements.removeAll(newEntries);
+                List<String> additionalElements = new ArrayList<>();
+                LOG.debug("Removing unused entries from the old collection - {}", cloneElements);
+
+                if (!cloneElements.isEmpty()) {
+                    for (String edgeIdForDelete : cloneElements) {
+                        Edge edge = graphHelper.getEdgeByEdgeId(instanceVertex, edgeLabel, edgeIdForDelete);
+                        boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(),
+                                attributeInfo.isComposite, true);
+                        if (!deleted) {
+                            additionalElements.add(edgeIdForDelete);
+                        }
                     }
                 }
+                return additionalElements;
             }
         }
+        return new ArrayList<>();
     }
 
-    private void getEdges(List<String> edgeIds, Map<String, Edge> edgeMap) {
-        if (edgeIds == null) {
-            return;
-        }
-
-        for (String edgeId : edgeIds) {
-            if (!edgeMap.containsKey(edgeId)) {
-                edgeMap.put(edgeId, graphHelper.getEdgeById(edgeId));
-            }
-        }
-    }
-
-
     /******************************************** MAP **************************************************/
 
     private void mapMapCollectionToVertex(ITypedInstance typedInstance, Vertex instanceVertex,
@@ -421,38 +399,81 @@ public final class TypedInstanceToGraphMapper {
 
         IDataType elementType = ((DataTypes.MapType) attributeInfo.dataType()).getValueType();
         String propertyName = GraphHelper.getQualifiedFieldName(typedInstance, attributeInfo);
-        List<String> currentElements = new ArrayList<>();
-        List<String> newElementsCreated = new ArrayList<>();
-        List<String> newKeysCreated = new ArrayList<>();
+
+        Map<String, String> currentMap = new HashMap<>();
+        Map<String, Object> newMap = new HashMap<>();
+
+        List<String> currentKeys = instanceVertex.getProperty(propertyName);
+        if (currentKeys != null && !currentKeys.isEmpty()) {
+            for (String key : currentKeys) {
+                String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(propertyName, key);
+                String propertyValueForKey = instanceVertex.getProperty(propertyNameForKey).toString();
+                currentMap.put(key, propertyValueForKey);
+            }
+        }
 
         if (!newAttributeEmpty) {
             for (Map.Entry entry : newAttribute.entrySet()) {
-                String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(propertyName, entry.getKey().toString());
-                newKeysCreated.add(entry.getKey().toString());
+                String keyStr = entry.getKey().toString();
+                String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(propertyName, keyStr);
 
-                String currentEntry = instanceVertex.getProperty(propertyNameForKey);
-                if (currentEntry != null) {
-                    currentElements.add(currentEntry);
-                }
-
-                String newEntry = addOrUpdateCollectionEntry(instanceVertex, attributeInfo, elementType,
-                        entry.getValue(), currentEntry, propertyNameForKey, operation);
+                Object newEntry = addOrUpdateCollectionEntry(instanceVertex, attributeInfo, elementType,
+                        entry.getValue(), currentMap.get(keyStr), propertyNameForKey, operation);
 
                 //Add/Update/Remove property value
                 GraphHelper.setProperty(instanceVertex, propertyNameForKey, newEntry);
-                newElementsCreated.add(newEntry);
+                newMap.put(keyStr, newEntry);
             }
         }
 
+        Map<String, String> additionalMap =
+                removeUnusedMapEntries(instanceVertex, propertyName, currentMap, newMap, elementType, attributeInfo);
+
+        Set<String> newKeys = new HashSet<>(newMap.keySet());
+        newKeys.addAll(additionalMap.keySet());
+
         // for dereference on way out
-        GraphHelper.setProperty(instanceVertex, propertyName, newKeysCreated);
+        GraphHelper.setProperty(instanceVertex, propertyName, new ArrayList<>(newKeys));
+    }
+
+    //Remove unused entries from map
+    private Map<String, String> removeUnusedMapEntries(Vertex instanceVertex, String propertyName,
+                                                       Map<String, String> currentMap,
+                                                       Map<String, Object> newMap, IDataType elementType,
+                                                       AttributeInfo attributeInfo)
+            throws AtlasException {
+        boolean reference = (elementType.getTypeCategory() == DataTypes.TypeCategory.STRUCT
+                || elementType.getTypeCategory() == DataTypes.TypeCategory.CLASS);
+        Map<String, String> additionalMap = new HashMap<>();
+
+        for (String currentKey : currentMap.keySet()) {
+            boolean shouldDeleteKey = !newMap.containsKey(currentKey);
+            if (reference) {
+                String currentEdge = currentMap.get(currentKey);
+                //Delete the edge reference if its not part of new edges created/updated
+                if (!newMap.values().contains(currentEdge)) {
+                    String edgeLabel = GraphHelper.getQualifiedNameForMapKey(propertyName, currentKey);
+                    Edge edge = graphHelper.getEdgeByEdgeId(instanceVertex, edgeLabel, currentMap.get(currentKey));
+                    boolean deleted =
+                            deleteHandler.deleteEdgeReference(edge, elementType.getTypeCategory(), attributeInfo.isComposite, true);
+                    if (!deleted) {
+                        additionalMap.put(currentKey, currentEdge);
+                        shouldDeleteKey = false;
+                    }
+                }
+            }
 
-        removeUnusedEntries(currentElements, newElementsCreated, elementType, attributeInfo);
+            if (shouldDeleteKey) {
+                String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(propertyName, currentKey);
+                graphHelper.setProperty(instanceVertex, propertyNameForKey, null);
+            }
+        }
+        return additionalMap;
     }
 
     /******************************************** ARRAY & MAP **************************************************/
 
-    private String addOrUpdateCollectionEntry(Vertex instanceVertex, AttributeInfo attributeInfo,
+    private Object addOrUpdateCollectionEntry(Vertex instanceVertex, AttributeInfo attributeInfo,
                                               IDataType elementType, Object newAttributeValue, String currentValue,
                                               String propertyName, Operation operation)
             throws AtlasException {
@@ -460,7 +481,7 @@ public final class TypedInstanceToGraphMapper {
         switch (elementType.getTypeCategory()) {
         case PRIMITIVE:
         case ENUM:
-            return newAttributeValue != null ? newAttributeValue.toString() : null;
+            return newAttributeValue != null ? newAttributeValue : null;
 
         case ARRAY:
         case MAP:
@@ -471,7 +492,7 @@ public final class TypedInstanceToGraphMapper {
         case STRUCT:
         case CLASS:
             final String edgeLabel = GraphHelper.EDGE_LABEL_PREFIX + propertyName;
-            Edge currentEdge = graphHelper.getEdgeById(currentValue);
+            Edge currentEdge = graphHelper.getEdgeByEdgeId(instanceVertex, edgeLabel, currentValue);
             return addOrUpdateReference(instanceVertex, attributeInfo, elementType, newAttributeValue, currentEdge,
                     edgeLabel, operation);
 
@@ -526,7 +547,7 @@ public final class TypedInstanceToGraphMapper {
         mapInstanceToVertex(structInstance, structInstanceVertex, structInstance.fieldMapping().fields, false,
                 Operation.CREATE);
         // add an edge to the newly created vertex from the parent
-        Edge newEdge = graphHelper.addEdge(instanceVertex, structInstanceVertex, edgeLabel);
+        Edge newEdge = graphHelper.getOrCreateEdge(instanceVertex, structInstanceVertex, edgeLabel);
 
         return newEdge;
     }
@@ -575,7 +596,7 @@ public final class TypedInstanceToGraphMapper {
 
     private Edge addClassEdge(Vertex instanceVertex, Vertex toVertex, String edgeLabel) throws AtlasException {
         // add an edge to the class vertex from the instance
-        return graphHelper.addEdge(instanceVertex, toVertex, edgeLabel);
+        return graphHelper.getOrCreateEdge(instanceVertex, toVertex, edgeLabel);
     }
 
     private Vertex getClassVertex(ITypedReferenceableInstance typedReference) throws EntityNotFoundException {
@@ -644,7 +665,7 @@ public final class TypedInstanceToGraphMapper {
 
         // add an edge to the newly created vertex from the parent
         String relationshipLabel = GraphHelper.getTraitLabel(entityType.getName(), traitName);
-        graphHelper.addEdge(parentInstanceVertex, traitInstanceVertex, relationshipLabel);
+        graphHelper.getOrCreateEdge(parentInstanceVertex, traitInstanceVertex, relationshipLabel);
     }
 
     /******************************************** PRIMITIVES **************************************************/

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/repository/typestore/GraphBackedTypeStore.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/typestore/GraphBackedTypeStore.java b/repository/src/main/java/org/apache/atlas/repository/typestore/GraphBackedTypeStore.java
index 3fb128c..5ed9e02 100755
--- a/repository/src/main/java/org/apache/atlas/repository/typestore/GraphBackedTypeStore.java
+++ b/repository/src/main/java/org/apache/atlas/repository/typestore/GraphBackedTypeStore.java
@@ -69,6 +69,8 @@ public class GraphBackedTypeStore implements ITypeStore {
 
     private final TitanGraph titanGraph;
 
+    private GraphHelper graphHelper = GraphHelper.getInstance();
+
     @Inject
     public GraphBackedTypeStore(GraphProvider<TitanGraph> graphProvider) {
         titanGraph = graphProvider.get();
@@ -155,7 +157,7 @@ public class GraphBackedTypeStore implements ITypeStore {
             for (String superTypeName : superTypes) {
                 HierarchicalType superType = typeSystem.getDataType(HierarchicalType.class, superTypeName);
                 Vertex superVertex = createVertex(superType.getTypeCategory(), superTypeName, superType.getDescription());
-                addEdge(vertex, superVertex, SUPERTYPE_EDGE_LABEL);
+                graphHelper.getOrCreateEdge(vertex, superVertex, SUPERTYPE_EDGE_LABEL);
             }
         }
     }
@@ -200,26 +202,11 @@ public class GraphBackedTypeStore implements ITypeStore {
             if (!coreTypes.contains(attrType.getName())) {
                 Vertex attrVertex = createVertex(attrType.getTypeCategory(), attrType.getName(), attrType.getDescription());
                 String label = getEdgeLabel(vertexTypeName, attribute.name);
-                addEdge(vertex, attrVertex, label);
+                graphHelper.getOrCreateEdge(vertex, attrVertex, label);
             }
         }
     }
 
-    private void addEdge(Vertex fromVertex, Vertex toVertex, String label) {
-        Iterator<Edge> edges = GraphHelper.getOutGoingEdgesByLabel(fromVertex, label);
-        // ATLAS-474: Check if this type system edge already exists, to avoid duplicates.
-        while (edges.hasNext()) {
-            Edge edge = edges.next();
-            if (edge.getVertex(Direction.IN).equals(toVertex)) {
-                LOG.debug("Edge from {} to {} with label {} already exists", 
-                    toString(fromVertex), toString(toVertex), label);
-                return;
-            }
-        }        
-        LOG.debug("Adding edge from {} to {} with label {}", toString(fromVertex), toString(toVertex), label);
-        titanGraph.addEdge(null, fromVertex, toVertex, label);
-    }
-
     @Override
     @GraphTransaction
     public TypesDef restore() throws AtlasException {

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
index 7cd83f8..c1af0f6 100755
--- a/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
+++ b/repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
@@ -26,6 +26,7 @@ import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasException;
 import org.apache.atlas.EntityAuditEvent;
+import org.apache.atlas.RequestContext;
 import org.apache.atlas.classification.InterfaceAudience;
 import org.apache.atlas.ha.HAConfiguration;
 import org.apache.atlas.listener.ActiveStateChangeHandler;
@@ -58,8 +59,6 @@ import org.apache.atlas.typesystem.types.Multiplicity;
 import org.apache.atlas.typesystem.types.StructTypeDefinition;
 import org.apache.atlas.typesystem.types.TraitType;
 import org.apache.atlas.typesystem.types.TypeSystem;
-import org.apache.atlas.typesystem.types.TypeUtils;
-import org.apache.atlas.typesystem.types.TypeUtils.Pair;
 import org.apache.atlas.typesystem.types.ValueConversionException;
 import org.apache.atlas.typesystem.types.utils.TypesUtil;
 import org.apache.atlas.utils.ParamChecker;
@@ -305,16 +304,15 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
      * Creates an entity, instance of the type.
      *
      * @param entityInstanceDefinition json array of entity definitions
-     * @return guids - json array of guids
+     * @return guids - list of guids
      */
     @Override
-    public String createEntities(String entityInstanceDefinition) throws AtlasException {
+    public List<String> createEntities(String entityInstanceDefinition) throws AtlasException {
         ParamChecker.notEmpty(entityInstanceDefinition, "Entity instance definition");
 
         ITypedReferenceableInstance[] typedInstances = deserializeClassInstances(entityInstanceDefinition);
 
-        List<String> guids = createEntities(typedInstances);
-        return new JSONArray(guids).toString();
+        return createEntities(typedInstances);
     }
 
     public List<String> createEntities(ITypedReferenceableInstance[] typedInstances) throws AtlasException {
@@ -422,25 +420,26 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
      * @return guids - json array of guids
      */
     @Override
-    public String updateEntities(String entityInstanceDefinition) throws AtlasException {
+    public AtlasClient.EntityResult updateEntities(String entityInstanceDefinition) throws AtlasException {
 
         ParamChecker.notEmpty(entityInstanceDefinition, "Entity instance definition");
         ITypedReferenceableInstance[] typedInstances = deserializeClassInstances(entityInstanceDefinition);
 
-        TypeUtils.Pair<List<String>, List<String>> guids = repository.updateEntities(typedInstances);
-        return onEntitiesAddedUpdated(guids);
+        AtlasClient.EntityResult entityResult = repository.updateEntities(typedInstances);
+        onEntitiesAddedUpdated(entityResult);
+        return entityResult;
     }
 
-    private String onEntitiesAddedUpdated(TypeUtils.Pair<List<String>, List<String>> guids) throws AtlasException {
-        onEntitiesAdded(guids.left);
-        onEntitiesUpdated(guids.right);
-
-        guids.left.addAll(guids.right);
-        return new JSONArray(guids.left).toString();
+    private void onEntitiesAddedUpdated(AtlasClient.EntityResult entityResult) throws AtlasException {
+        onEntitiesAdded(entityResult.getCreatedEntities());
+        onEntitiesUpdated(entityResult.getUpdateEntities());
+        //Note: doesn't access deletedEntities from entityResult
+        onEntitiesDeleted(RequestContext.get().getDeletedEntities());
     }
 
     @Override
-    public String updateEntityAttributeByGuid(final String guid, String attributeName, String value) throws AtlasException {
+    public AtlasClient.EntityResult updateEntityAttributeByGuid(final String guid, String attributeName,
+                                                                String value) throws AtlasException {
         ParamChecker.notEmpty(guid, "entity id");
         ParamChecker.notEmpty(attributeName, "attribute name");
         ParamChecker.notEmpty(value, "attribute value");
@@ -469,8 +468,9 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         }
 
         ((ReferenceableInstance)newInstance).replaceWithNewId(new Id(guid, 0, newInstance.getTypeName()));
-        TypeUtils.Pair<List<String>, List<String>> guids = repository.updatePartial(newInstance);
-        return onEntitiesAddedUpdated(guids);
+        AtlasClient.EntityResult entityResult = repository.updatePartial(newInstance);
+        onEntitiesAddedUpdated(entityResult);
+        return entityResult;
     }
 
     private ITypedReferenceableInstance validateEntityExists(String guid)
@@ -483,7 +483,8 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
     }
 
     @Override
-    public String updateEntityPartialByGuid(final String guid, Referenceable newEntity) throws AtlasException {
+    public AtlasClient.EntityResult updateEntityPartialByGuid(final String guid, Referenceable newEntity)
+            throws AtlasException {
         ParamChecker.notEmpty(guid, "guid cannot be null");
         ParamChecker.notNull(newEntity, "updatedEntity cannot be null");
         ITypedReferenceableInstance existInstance = validateEntityExists(guid);
@@ -491,11 +492,13 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         ITypedReferenceableInstance newInstance = convertToTypedInstance(newEntity, existInstance.getTypeName());
         ((ReferenceableInstance)newInstance).replaceWithNewId(new Id(guid, 0, newInstance.getTypeName()));
 
-        TypeUtils.Pair<List<String>, List<String>> guids = repository.updatePartial(newInstance);
-        return onEntitiesAddedUpdated(guids);
+        AtlasClient.EntityResult entityResult = repository.updatePartial(newInstance);
+        onEntitiesAddedUpdated(entityResult);
+        return entityResult;
     }
 
-    private ITypedReferenceableInstance convertToTypedInstance(Referenceable updatedEntity, String typeName) throws AtlasException {
+    private ITypedReferenceableInstance convertToTypedInstance(Referenceable updatedEntity, String typeName)
+            throws AtlasException {
         ClassType type = typeSystem.getDataType(ClassType.class, typeName);
         ITypedReferenceableInstance newInstance = type.createInstance();
 
@@ -538,8 +541,9 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
     }
 
     @Override
-    public String updateEntityByUniqueAttribute(String typeName, String uniqueAttributeName, String attrValue,
-                                                Referenceable updatedEntity) throws AtlasException {
+    public AtlasClient.EntityResult updateEntityByUniqueAttribute(String typeName, String uniqueAttributeName,
+                                                                  String attrValue,
+                                                                  Referenceable updatedEntity) throws AtlasException {
         ParamChecker.notEmpty(typeName, "typeName");
         ParamChecker.notEmpty(uniqueAttributeName, "uniqueAttributeName");
         ParamChecker.notNull(attrValue, "unique attribute value");
@@ -550,8 +554,9 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         final ITypedReferenceableInstance newInstance = convertToTypedInstance(updatedEntity, typeName);
         ((ReferenceableInstance)newInstance).replaceWithNewId(oldInstance.getId());
 
-        TypeUtils.Pair<List<String>, List<String>> guids = repository.updatePartial(newInstance);
-        return onEntitiesAddedUpdated(guids);
+        AtlasClient.EntityResult entityResult = repository.updatePartial(newInstance);
+        onEntitiesAddedUpdated(entityResult);
+        return entityResult;
     }
 
     private void validateTypeExists(String entityType) throws AtlasException {
@@ -726,13 +731,14 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
      * @see org.apache.atlas.services.MetadataService#deleteEntities(java.lang.String)
      */
     @Override
-    public List<String> deleteEntities(List<String> deleteCandidateGuids) throws AtlasException {
+    public AtlasClient.EntityResult deleteEntities(List<String> deleteCandidateGuids) throws AtlasException {
         ParamChecker.notEmpty(deleteCandidateGuids, "delete candidate guids");
         return deleteGuids(deleteCandidateGuids);
     }
 
     @Override
-    public List<String> deleteEntityByUniqueAttribute(String typeName, String uniqueAttributeName, String attrValue) throws AtlasException {
+    public AtlasClient.EntityResult deleteEntityByUniqueAttribute(String typeName, String uniqueAttributeName,
+                                                                  String attrValue) throws AtlasException {
         ParamChecker.notEmpty(typeName, "delete candidate typeName");
         ParamChecker.notEmpty(uniqueAttributeName, "delete candidate unique attribute name");
         ParamChecker.notEmpty(attrValue, "delete candidate unique attribute value");
@@ -745,12 +751,10 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
         return deleteGuids(deleteCandidateGuids);
     }
 
-    private List<String> deleteGuids(List<String> deleteCandidateGuids) throws AtlasException {
-        Pair<List<String>, List<ITypedReferenceableInstance>> deleteEntitiesResult = repository.deleteEntities(deleteCandidateGuids);
-        if (deleteEntitiesResult.right.size() > 0) {
-            onEntitiesDeleted(deleteEntitiesResult.right);
-        }
-        return deleteEntitiesResult.left;
+    private AtlasClient.EntityResult deleteGuids(List<String> deleteCandidateGuids) throws AtlasException {
+        AtlasClient.EntityResult entityResult = repository.deleteEntities(deleteCandidateGuids);
+        onEntitiesAddedUpdated(entityResult);
+        return entityResult;
     }
 
     private void onEntitiesDeleted(List<ITypedReferenceableInstance> entities) throws AtlasException {

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
index be407a5..f699404 100644
--- a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
+++ b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
@@ -19,6 +19,7 @@
 package org.apache.atlas.repository.audit;
 
 import org.apache.atlas.EntityAuditEvent;
+import org.apache.atlas.typesystem.Referenceable;
 import org.apache.commons.lang.RandomStringUtils;
 import org.testng.annotations.Test;
 
@@ -38,7 +39,7 @@ public class AuditRepositoryTestBase {
     @Test
     public void testAddEvents() throws Exception {
         EntityAuditEvent event = new EntityAuditEvent(rand(), System.currentTimeMillis(), "u1",
-                EntityAuditEvent.EntityAuditAction.ENTITY_CREATE, "d1");
+                EntityAuditEvent.EntityAuditAction.ENTITY_CREATE, "d1", new Referenceable(rand()));
 
         eventRepository.putEvents(event);
 
@@ -54,17 +55,18 @@ public class AuditRepositoryTestBase {
         String id2 = "id2" + rand();
         String id3 = "id3" + rand();
         long ts = System.currentTimeMillis();
+        Referenceable entity = new Referenceable(rand());
         List<EntityAuditEvent> expectedEvents = new ArrayList<>(3);
         for (int i = 0; i < 3; i++) {
             //Add events for both ids
             EntityAuditEvent event = new EntityAuditEvent(id2, ts - i, "user" + i,
-                            EntityAuditEvent.EntityAuditAction.ENTITY_UPDATE, "details" + i);
+                            EntityAuditEvent.EntityAuditAction.ENTITY_UPDATE, "details" + i, entity);
             eventRepository.putEvents(event);
             expectedEvents.add(event);
             eventRepository.putEvents(new EntityAuditEvent(id1, ts - i, "user" + i,
-                    EntityAuditEvent.EntityAuditAction.TAG_DELETE, "details" + i));
+                    EntityAuditEvent.EntityAuditAction.TAG_DELETE, "details" + i, entity));
             eventRepository.putEvents(new EntityAuditEvent(id3, ts - i, "user" + i,
-                    EntityAuditEvent.EntityAuditAction.TAG_ADD, "details" + i));
+                    EntityAuditEvent.EntityAuditAction.TAG_ADD, "details" + i, entity));
         }
 
         //Use ts for which there is no event - ts + 2

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryDeleteTestBase.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryDeleteTestBase.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryDeleteTestBase.java
index 1aeedb5..449e066 100644
--- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryDeleteTestBase.java
+++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryDeleteTestBase.java
@@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet;
 import com.thinkaurelius.titan.core.TitanGraph;
 import com.thinkaurelius.titan.core.util.TitanCleanup;
 import com.tinkerpop.blueprints.Vertex;
-
 import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasException;
 import org.apache.atlas.RepositoryMetadataModule;
@@ -50,7 +49,6 @@ import org.apache.atlas.typesystem.types.Multiplicity;
 import org.apache.atlas.typesystem.types.StructTypeDefinition;
 import org.apache.atlas.typesystem.types.TraitType;
 import org.apache.atlas.typesystem.types.TypeSystem;
-import org.apache.atlas.typesystem.types.TypeUtils;
 import org.apache.atlas.typesystem.types.utils.TypesUtil;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
@@ -60,7 +58,6 @@ import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
 import javax.inject.Inject;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -71,6 +68,7 @@ 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.NAME;
+import static org.apache.atlas.TestUtils.PII;
 import static org.apache.atlas.TestUtils.PROCESS_TYPE;
 import static org.apache.atlas.TestUtils.TABLE_TYPE;
 import static org.apache.atlas.TestUtils.createColumnEntity;
@@ -78,8 +76,6 @@ import static org.apache.atlas.TestUtils.createDBEntity;
 import static org.apache.atlas.TestUtils.createTableEntity;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -145,7 +141,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         assertEquals(instance.getId()._getId(), id);
 
         //delete entity should mark it as deleted
-        List<String> results = deleteEntities(id);
+        List<String> results = deleteEntities(id).getDeletedEntities();
         assertEquals(results.get(0), id);
         assertEntityDeleted(id);
 
@@ -167,6 +163,26 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
     }
 
     @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();
@@ -179,13 +195,16 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         table.set(COLUMNS_ATTR_NAME, Arrays.asList(new Id(colId, 0, COLUMN_TYPE)));
         String tableId = createInstance(table);
 
-        deleteEntities(colId);
+        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);
-        List<ITypedReferenceableInstance> columns =
-                (List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
-        assertNull(columns);
+        assertColumnForTestDeleteReference(tableInstance);
 
         //Deleting table should update process
         Referenceable process = new Referenceable(PROCESS_TYPE);
@@ -195,18 +214,23 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
 
         deleteEntities(tableId);
         assertEntityDeleted(tableId);
-        assertTestDeleteReference(processInstance);
+
+        assertTableForTestDeleteReference(tableId);
+        assertProcessForTestDeleteReference(processInstance);
     }
 
-    protected abstract void assertTestDeleteReference(ITypedReferenceableInstance processInstance) throws Exception;
+    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 List<String> deleteEntities(String... id) throws Exception {
+    private AtlasClient.EntityResult deleteEntities(String... id) throws Exception {
         RequestContext.createContext();
-        List<String> response = repositoryService.deleteEntities(Arrays.asList(id)).left;
-        assertNotNull(response);
-        return response;
+        return repositoryService.deleteEntities(Arrays.asList(id));
     }
 
     private String createInstance(Referenceable entity) throws Exception {
@@ -228,21 +252,41 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         table1Entity.set(COLUMNS_ATTR_NAME, ImmutableList.of(col1, col2, col3));
         createInstance(table1Entity);
 
-        // Retrieve the table entities from the auditRepository,
-        // to get their guids and the composite column guids.
+        // 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> table1Columns = (List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_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);
 
-        // Delete the table entities.  The deletion should cascade
-        // to their composite columns.
-        List<String> deletedGuids = deleteEntities(tableInstance.getId()._getId());
+        //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()));
-        for (IReferenceableInstance column : table1Columns) {
-            Assert.assertTrue(deletedGuids.contains(column.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) {
@@ -251,6 +295,8 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         assertTestDeleteEntities(tableInstance);
     }
 
+    protected abstract void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException;
+
     protected abstract void assertTestDeleteEntities(ITypedReferenceableInstance tableInstance) throws Exception;
 
     /**
@@ -276,12 +322,13 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "SecurityClearance").size();
         Assert.assertEquals(vertexCount, 1);
 
-        List<String> deletedEntities = deleteEntities(hrDeptGuid);
+        List<String> deletedEntities = deleteEntities(hrDeptGuid).getDeletedEntities();
         assertTrue(deletedEntities.contains(hrDeptGuid));
+        assertEntityDeleted(hrDeptGuid);
 
         // Verify Department entity and its contained Person entities were deleted.
-        assertEntityDeleted(hrDeptGuid);
         for (String employeeGuid : employeeGuids) {
+            assertTrue(deletedEntities.contains(employeeGuid));
             assertEntityDeleted(employeeGuid);
         }
 
@@ -341,15 +388,16 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         object = mapOwnerVertex.getProperty(atlasEdgeLabel.getQualifiedMapKey());
         Assert.assertNotNull(object);
 
-        List<String> deletedEntities = deleteEntities(mapOwnerGuid);
+        List<String> deletedEntities = deleteEntities(mapOwnerGuid).getDeletedEntities();
         Assert.assertEquals(deletedEntities.size(), 2);
-        Assert.assertTrue(deletedEntities.containsAll(guids));
+        Assert.assertTrue(deletedEntities.contains(mapOwnerGuid));
+        Assert.assertTrue(deletedEntities.contains(mapValueGuid));
 
         assertEntityDeleted(mapOwnerGuid);
         assertEntityDeleted(mapValueGuid);
     }
 
-    private TypeUtils.Pair<List<String>, List<String>> updatePartial(ITypedReferenceableInstance entity) throws RepositoryException {
+    private AtlasClient.EntityResult updatePartial(ITypedReferenceableInstance entity) throws RepositoryException {
         RequestContext.createContext();
         return repositoryService.updatePartial(entity);
     }
@@ -379,7 +427,9 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         ClassType personType = typeSystem.getDataType(ClassType.class, "Person");
         ITypedReferenceableInstance maxEntity = personType.createInstance(max.getId());
         maxEntity.set("mentor", johnGuid);
-        updatePartial(maxEntity);
+        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);
@@ -394,7 +444,9 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
 
         // Update max's mentor reference to jane.
         maxEntity.set("mentor", janeGuid);
-        updatePartial(maxEntity);
+        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);
@@ -411,7 +463,11 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         Id juliusGuid = julius.getId();
         maxEntity = personType.createInstance(max.getId());
         maxEntity.set("manager", juliusGuid);
-        updatePartial(maxEntity);
+        entityResult = updatePartial(maxEntity);
+        //TODO ATLAS-499 should have updated julius' subordinates
+        assertEquals(entityResult.getUpdateEntities().size(), 2);
+        assertTrue(entityResult.getUpdateEntities().contains(maxGuid));
+        assertTrue(entityResult.getUpdateEntities().contains(janeGuid._getId()));
 
         // Verify the update was applied correctly - julius should now be max's manager.
         max = repositoryService.getEntityDefinition(maxGuid);
@@ -456,41 +512,38 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         }
         Assert.assertTrue(subordinateIds.contains(maxGuid));
 
-        List<String> deletedEntities = deleteEntities(maxGuid);
-        Assert.assertTrue(deletedEntities.contains(maxGuid));
-        assertEntityDeleted(maxGuid);
 
-        // Verify that the Department.employees reference to the deleted employee
-        // was disconnected.
-        hrDept = repositoryService.getEntityDefinition(hrDeptGuid);
-        refValue = hrDept.get("employees");
-        Assert.assertTrue(refValue instanceof List);
-        List<Object> employees = (List<Object>)refValue;
-        Assert.assertEquals(employees.size(), 3);
-        for (Object listValue : employees) {
-            Assert.assertTrue(listValue instanceof ITypedReferenceableInstance);
-            ITypedReferenceableInstance employee = (ITypedReferenceableInstance) listValue;
-            Assert.assertNotEquals(employee.getId()._getId(), maxGuid);
-        }
+        AtlasClient.EntityResult entityResult = deleteEntities(maxGuid);
+        ITypedReferenceableInstance john = repositoryService.getEntityDefinition("Manager", "name", "John");
 
-        // Verify that max's Person.mentor unidirectional reference to john was disconnected.
-        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(johnGuid);
-        refValue = john.get("mentor");
-        Assert.assertNull(refValue);
+        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);
 
-        assertTestDisconnectBidirectionalReferences(janeGuid);
+        assertMaxForTestDisconnectBidirectionalReferences(nameGuidMap);
 
         // Now delete jane - this should disconnect the manager reference from her
         // subordinate.
-        deletedEntities = deleteEntities(janeGuid);
-        Assert.assertTrue(deletedEntities.contains(janeGuid));
+        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(johnGuid);
-        Assert.assertNull(john.get("manager"));
+        john = repositoryService.getEntityDefinition("Person", "name", "John");
+        assertJohnForTestDisconnectBidirectionalReferences(john, janeGuid);
     }
 
-    protected abstract void assertTestDisconnectBidirectionalReferences(String janeGuid) throws Exception;
+    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
@@ -503,30 +556,27 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         // 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();
-        Object refValues = table.get("columns");
-        Assert.assertTrue(refValues instanceof List);
-        List<Object> refList = (List<Object>) refValues;
-        Assert.assertEquals(refList.size(), 5);
-        Assert.assertTrue(refList.get(0) instanceof ITypedReferenceableInstance);
-        ITypedReferenceableInstance column = (ITypedReferenceableInstance) refList.get(0);
-        String columnGuid = column.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.
-        List<String> deletedEntities = deleteEntities(columnGuid);
-        Assert.assertTrue(deletedEntities.contains(columnGuid));
+        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);
-        refList = (List<Object>) table.get("columns");
-        Assert.assertEquals(refList.size(), 4);
-        for (Object refValue : refList) {
-            Assert.assertTrue(refValue instanceof ITypedReferenceableInstance);
-            column = (ITypedReferenceableInstance)refValue;
-            Assert.assertFalse(column.getId()._getId().equals(columnGuid));
-        }
+        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.
@@ -559,8 +609,8 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         Referenceable structTargetEntity = new Referenceable("StructTarget");
         Referenceable traitTargetEntity = new Referenceable("TraitTarget");
         Referenceable structContainerEntity = new Referenceable("StructContainer");
-        Referenceable structInstance = new Referenceable("TestStruct");
-        Referenceable nestedStructInstance = new Referenceable("NestedStruct");
+        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));
@@ -623,19 +673,19 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         Assert.assertEquals(refList.get(0).getId()._getId(), traitTargetGuid);
 
         // Delete the entities that are targets of the struct and trait instances.
-        List<String> deletedEntities = deleteEntities(structTargetGuid, traitTargetGuid);
+        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);
-        Assert.assertEquals(deletedEntities.size(), 2);
-        Assert.assertTrue(deletedEntities.containsAll(Arrays.asList(structTargetGuid, traitTargetGuid)));
 
         assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(structContainerGuid);
 
         // Delete the entity which contains nested structs and has the TestTrait trait.
-        deletedEntities = deleteEntities(structContainerGuid);
+        entityResult = deleteEntities(structContainerGuid);
+        Assert.assertEquals(entityResult.getDeletedEntities().size(), 1);
+        Assert.assertTrue(entityResult.getDeletedEntities().contains(structContainerGuid));
         assertEntityDeleted(structContainerGuid);
-        Assert.assertEquals(deletedEntities.size(), 1);
-        Assert.assertTrue(deletedEntities.contains(structContainerGuid));
 
         // Verify all TestStruct struct vertices were removed.
         assertVerticesDeleted(getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, "TestStruct"));
@@ -890,13 +940,14 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
         return list;
     }
 
-    private Map<String, String> getEmployeeNameGuidMap(ITypedReferenceableInstance hrDept) throws AtlasException {
-
+    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>();
+        Map<String, String> nameGuidMap = new HashMap<String, String>() {{
+            put("hr", hrDept.getId()._getId());
+        }};
 
         for (Object listValue : employees) {
             Assert.assertTrue(listValue instanceof ITypedReferenceableInstance);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositoryHardDeleteTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositoryHardDeleteTest.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositoryHardDeleteTest.java
index d2109d3..cc60264 100644
--- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositoryHardDeleteTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositoryHardDeleteTest.java
@@ -21,8 +21,10 @@ package org.apache.atlas.repository.graph;
 import com.tinkerpop.blueprints.Vertex;
 
 import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasException;
 import org.apache.atlas.TestUtils;
 import org.apache.atlas.repository.Constants;
+import org.apache.atlas.typesystem.IReferenceableInstance;
 import org.apache.atlas.typesystem.IStruct;
 import org.apache.atlas.typesystem.ITypedReferenceableInstance;
 import org.apache.atlas.typesystem.ITypedStruct;
@@ -32,8 +34,11 @@ import org.apache.atlas.typesystem.types.TypeSystem;
 import org.testng.Assert;
 
 import java.util.List;
+import java.util.Map;
 
+import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.fail;
 import static org.testng.AssertJUnit.assertNotNull;
@@ -45,7 +50,24 @@ public class GraphBackedRepositoryHardDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
-    protected void assertTestDeleteReference(ITypedReferenceableInstance processInstance) throws Exception {
+    protected void assertTestDeleteEntityWithTraits(String guid) {
+        //entity is deleted. So, no assertions
+    }
+
+    @Override
+    protected void assertTableForTestDeleteReference(String tableId) {
+        //entity is deleted. So, no assertions
+    }
+
+    @Override
+    protected void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance) throws AtlasException {
+        List<ITypedReferenceableInstance> columns =
+                (List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
+        assertNull(columns);
+    }
+
+    @Override
+    protected void assertProcessForTestDeleteReference(ITypedReferenceableInstance processInstance) throws Exception {
         //assert that outputs is empty
         ITypedReferenceableInstance newProcess =
                 repositoryService.getEntityDefinition(processInstance.getId()._getId());
@@ -63,6 +85,11 @@ public class GraphBackedRepositoryHardDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
+    protected void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException {
+        assertEquals(((List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME)).size(), 2);
+    }
+
+    @Override
     protected void assertTestDeleteEntities(ITypedReferenceableInstance tableInstance) {
         int vertexCount = getVertices(Constants.ENTITY_TYPE_PROPERTY_KEY, TestUtils.TABLE_TYPE).size();
         assertEquals(vertexCount, 0);
@@ -85,12 +112,42 @@ public class GraphBackedRepositoryHardDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
-    protected void assertTestDisconnectBidirectionalReferences(String janeGuid) throws Exception {
+    protected void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john,
+                                                                      String janeGuid) throws Exception {
+        assertNull(john.get("manager"));
+    }
+
+    @Override
+    protected void assertMaxForTestDisconnectBidirectionalReferences(Map<String, String> nameGuidMap)
+            throws Exception {
+        // Verify that the Department.employees reference to the deleted employee
+        // was disconnected.
+        ITypedReferenceableInstance hrDept = repositoryService.getEntityDefinition(nameGuidMap.get("hr"));
+        List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) hrDept.get("employees");
+        Assert.assertEquals(employees.size(), 3);
+        String maxGuid = nameGuidMap.get("Max");
+        for (ITypedReferenceableInstance employee : employees) {
+            Assert.assertNotEquals(employee.getId()._getId(), maxGuid);
+        }
+
         // Verify that the Manager.subordinates reference to the deleted employee
         // Max was disconnected.
-        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(janeGuid);
+        ITypedReferenceableInstance jane = repositoryService.getEntityDefinition(nameGuidMap.get("Jane"));
         List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates");
         assertEquals(subordinates.size(), 1);
+
+        // Verify that max's Person.mentor unidirectional reference to john was disconnected.
+        ITypedReferenceableInstance john = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
+        assertNull(john.get("mentor"));
+    }
+
+    @Override
+    protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
+            List<ITypedReferenceableInstance> columns, String columnGuid) {
+        assertEquals(columns.size(), 4);
+        for (ITypedReferenceableInstance column : columns) {
+            assertFalse(column.getId()._getId().equals(columnGuid));
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/705014eb/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositorySoftDeleteTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositorySoftDeleteTest.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositorySoftDeleteTest.java
index d9e3ec9..90bb635 100644
--- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositorySoftDeleteTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedRepositorySoftDeleteTest.java
@@ -19,10 +19,11 @@
 package org.apache.atlas.repository.graph;
 
 import com.tinkerpop.blueprints.Vertex;
-
 import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasException;
 import org.apache.atlas.TestUtils;
 import org.apache.atlas.repository.Constants;
+import org.apache.atlas.typesystem.IReferenceableInstance;
 import org.apache.atlas.typesystem.IStruct;
 import org.apache.atlas.typesystem.ITypedReferenceableInstance;
 import org.apache.atlas.typesystem.ITypedStruct;
@@ -33,8 +34,12 @@ import org.testng.Assert;
 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.apache.atlas.TestUtils.PII;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
 public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepositoryDeleteTestBase {
     @Override
@@ -43,7 +48,38 @@ public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
-    protected void assertTestDeleteReference(ITypedReferenceableInstance expected) throws Exception {
+    protected void assertTestDeleteEntityWithTraits(String guid) throws Exception {
+        ITypedReferenceableInstance instance = repositoryService.getEntityDefinition(guid);
+        assertTrue(instance.getTraits().contains(PII));
+    }
+
+    @Override
+    protected void assertTableForTestDeleteReference(String tableId) throws Exception  {
+        ITypedReferenceableInstance table = repositoryService.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 = repositoryService.getEntityDefinition(dbId.getId()._getId());
+        assertNotNull(db);
+        assertEquals(db.getId().getState(), Id.EntityState.ACTIVE);
+    }
+
+    @Override
+    protected void assertColumnForTestDeleteReference(ITypedReferenceableInstance tableInstance) throws AtlasException {
+        List<ITypedReferenceableInstance> columns =
+                (List<ITypedReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
+        assertEquals(columns.size(), 1);
+        assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
+    }
+
+    @Override
+    protected void assertProcessForTestDeleteReference(ITypedReferenceableInstance expected) throws Exception {
         ITypedReferenceableInstance process = repositoryService.getEntityDefinition(expected.getId()._getId());
         List<ITypedReferenceableInstance> outputs =
                 (List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS);
@@ -59,6 +95,13 @@ public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
+    protected void assertDeletedColumn(ITypedReferenceableInstance tableInstance) throws AtlasException {
+        List<IReferenceableInstance> columns = (List<IReferenceableInstance>) tableInstance.get(COLUMNS_ATTR_NAME);
+        assertEquals(columns.size(), 3);
+        assertEquals(columns.get(0).getId().getState(), Id.EntityState.DELETED);
+    }
+
+    @Override
     protected void assertTestDeleteEntities(ITypedReferenceableInstance expected) throws Exception {
         //Assert that the deleted table can be fully constructed back
         ITypedReferenceableInstance table = repositoryService.getEntityDefinition(expected.getId()._getId());
@@ -67,6 +110,7 @@ public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepo
         List<ITypedReferenceableInstance> expectedColumns =
                 (List<ITypedReferenceableInstance>) table.get(TestUtils.COLUMNS_ATTR_NAME);
         assertEquals(columns.size(), expectedColumns.size());
+        assertNotNull(table.get("database"));
     }
 
     @Override
@@ -85,11 +129,57 @@ public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepo
     }
 
     @Override
-    protected void assertTestDisconnectBidirectionalReferences(String janeGuid) throws Exception {
+    protected void assertJohnForTestDisconnectBidirectionalReferences(ITypedReferenceableInstance john, 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(Map<String, String> nameGuidMap) throws Exception {
+        // Verify that the Department.employees reference to the deleted employee
+        // was disconnected.
+        ITypedReferenceableInstance hrDept = repositoryService.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 = repositoryService.getEntityDefinition(janeGuid);
+        ITypedReferenceableInstance jane = repositoryService.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 = repositoryService.getEntityDefinition(nameGuidMap.get("John"));
+        Id mentor = (Id) john.get("mentor");
+        assertEquals(mentor._getId(), maxGuid);
+        assertEquals(mentor.getState(), Id.EntityState.DELETED);
+    }
+
+    @Override
+    protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(
+            List<ITypedReferenceableInstance> columns, String columnGuid) {
+        Assert.assertEquals(columns.size(), 5);
+        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
@@ -122,7 +212,6 @@ public class GraphBackedRepositorySoftDeleteTest extends GraphBackedMetadataRepo
 
     @Override
     protected void assertTestDeleteTargetOfMultiplicityRequiredReference() throws Exception {
-
         // No-op - it's ok that no exception was thrown if soft deletes are enabled.
     }
 }