You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sa...@apache.org on 2017/08/30 00:01:38 UTC

atlas git commit: ATLAS-2040: Relationship with many-to-many cardinality gives incorrect relationship attribute value

Repository: atlas
Updated Branches:
  refs/heads/master 1b7e41f1a -> f59284adb


ATLAS-2040: Relationship with many-to-many cardinality gives incorrect relationship attribute value


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/f59284ad
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/f59284ad
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/f59284ad

Branch: refs/heads/master
Commit: f59284adbb3f0231fe6cc0da3a521c29f0210dba
Parents: 1b7e41f
Author: Sarath Subramanian <ss...@hortonworks.com>
Authored: Tue Aug 29 17:01:00 2017 -0700
Committer: Sarath Subramanian <ss...@hortonworks.com>
Committed: Tue Aug 29 17:01:00 2017 -0700

----------------------------------------------------------------------
 .../atlas/type/AtlasRelationshipType.java       |  41 +++---
 .../org/apache/atlas/type/AtlasStructType.java  |   2 +-
 .../apache/atlas/TestRelationshipUtilsV2.java   |  86 ++++++++---
 .../atlas/repository/graph/GraphHelper.java     |  72 ++++++----
 .../store/graph/v1/DeleteHandlerV1.java         |  17 ++-
 .../store/graph/v1/EntityGraphMapper.java       | 102 ++++++++++---
 .../store/graph/v1/EntityGraphRetriever.java    |   9 +-
 .../AtlasRelationshipStoreHardDeleteV1Test.java |  60 +++++++-
 .../AtlasRelationshipStoreSoftDeleteV1Test.java |  63 +++++++-
 .../graph/v1/AtlasRelationshipStoreV1Test.java  | 142 ++++++++++++++++---
 10 files changed, 481 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
index 3de02d0..aa26d18 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
@@ -31,6 +31,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
 import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
 import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
 
@@ -118,24 +119,33 @@ public class AtlasRelationshipType extends AtlasStructType {
     }
 
     private void addRelationshipEdgeDirection() {
-        AtlasRelationshipEndDef endDef1       = relationshipDef.getEndDef1();
-        AtlasRelationshipEndDef endDef2       = relationshipDef.getEndDef2();
-        AtlasAttribute          end1Attribute = end1Type.getRelationshipAttribute(endDef1.getName());
-        AtlasAttribute          end2Attribute = end2Type.getRelationshipAttribute(endDef2.getName());
+        AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1();
+        AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2();
 
-        //default relationship edge direction is end1 (out) -> end2 (in)
-        AtlasRelationshipEdgeDirection end1Direction = OUT;
-        AtlasRelationshipEdgeDirection end2Direction = IN;
+        if (StringUtils.equals(endDef1.getType(), endDef2.getType()) &&
+                StringUtils.equals(endDef1.getName(), endDef2.getName())) {
 
-        if (endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
-            end2Direction = OUT;
-        } else if (!endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
-            end1Direction = IN;
-            end2Direction = OUT;
-        }
+            AtlasAttribute endAttribute = end1Type.getRelationshipAttribute(endDef1.getName());
 
-        end1Attribute.setRelationshipEdgeDirection(end1Direction);
-        end2Attribute.setRelationshipEdgeDirection(end2Direction);
+            endAttribute.setRelationshipEdgeDirection(BOTH);
+        } else {
+            AtlasAttribute end1Attribute = end1Type.getRelationshipAttribute(endDef1.getName());
+            AtlasAttribute end2Attribute = end2Type.getRelationshipAttribute(endDef2.getName());
+
+            //default relationship edge direction is end1 (out) -> end2 (in)
+            AtlasRelationshipEdgeDirection end1Direction = OUT;
+            AtlasRelationshipEdgeDirection end2Direction = IN;
+
+            if (endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
+                end2Direction = OUT;
+            } else if (!endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
+                end1Direction = IN;
+                end2Direction = OUT;
+            }
+
+            end1Attribute.setRelationshipEdgeDirection(end1Direction);
+            end2Attribute.setRelationshipEdgeDirection(end2Direction);
+        }
     }
 
     @Override
@@ -200,7 +210,6 @@ public class AtlasRelationshipType extends AtlasStructType {
         AtlasRelationshipEndDef endDef2              = relationshipDef.getEndDef2();
         RelationshipCategory    relationshipCategory = relationshipDef.getRelationshipCategory();
         String                  name                 = relationshipDef.getName();
-
         boolean                 isContainer1         = endDef1.getIsContainer();
         boolean                 isContainer2         = endDef2.getIsContainer();
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
index 6f30ff3..1c202e7 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
@@ -794,6 +794,6 @@ public class AtlasStructType extends AtlasType {
         private static final char   DOUBLE_QUOTE_CHAR       = '"';
         private static final char   SPACE_CHAR              = ' ';
 
-        public enum AtlasRelationshipEdgeDirection { IN, OUT }
+        public enum AtlasRelationshipEdgeDirection { IN, OUT, BOTH }
     }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/intg/src/test/java/org/apache/atlas/TestRelationshipUtilsV2.java
----------------------------------------------------------------------
diff --git a/intg/src/test/java/org/apache/atlas/TestRelationshipUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestRelationshipUtilsV2.java
index 98be2b8..d0effd6 100755
--- a/intg/src/test/java/org/apache/atlas/TestRelationshipUtilsV2.java
+++ b/intg/src/test/java/org/apache/atlas/TestRelationshipUtilsV2.java
@@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableSet;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.instance.AtlasEntity;
 import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
+import org.apache.atlas.model.instance.AtlasObjectId;
 import org.apache.atlas.model.instance.AtlasStruct;
-import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
 import org.apache.atlas.model.typedef.AtlasClassificationDef;
 import org.apache.atlas.model.typedef.AtlasEntityDef;
 import org.apache.atlas.model.typedef.AtlasEnumDef;
@@ -33,18 +33,17 @@ import org.apache.atlas.model.typedef.AtlasRelationshipDef;
 import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
 import org.apache.atlas.model.typedef.AtlasStructDef;
 import org.apache.atlas.model.typedef.AtlasTypesDef;
-import org.apache.atlas.type.AtlasTypeUtil;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.getArrayTypeName;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.getMapTypeName;
+import static org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags.BOTH;
 import static org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags.ONE_TO_TWO;
 import static org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory.AGGREGATION;
 import static org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory.ASSOCIATION;
@@ -72,12 +71,13 @@ public final class TestRelationshipUtilsV2 {
     public static final String EMPLOYEE_TYPE            = "Employee";
     public static final String EMPLOYEE_DEPARTMENT_TYPE = "EmployeeDepartment";
     public static final String EMPLOYEE_MANAGER_TYPE    = "EmployeeManager";
-    public static final String EMPLOYEE_MENTOR_TYPE     = "EmployeeMentor";
+    public static final String EMPLOYEE_MENTORS_TYPE    = "EmployeeMentors";
+    public static final String EMPLOYEE_FRIENDS_TYPE    = "EmployeeFriends";
+    public static final String PERSON_SIBLING_TYPE      = "PersonSibling";
     public static final String TYPE_A                   = "A";
     public static final String TYPE_B                   = "B";
     public static final String DEFAULT_VERSION          = "1.0";
 
-
     private TestRelationshipUtilsV2() { }
 
     public static AtlasTypesDef getDepartmentEmployeeTypes() throws AtlasBaseException {
@@ -121,23 +121,36 @@ public final class TestRelationshipUtilsV2 {
                                                         DEFAULT_VERSION, AGGREGATION, ONE_TO_TWO,
                                                         new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "department", SINGLE),
                                                         new AtlasRelationshipEndDef(DEPARTMENT_TYPE, "employees", SET, true));
+
         /******* [Manager -> Employee] Relationship *******/
         AtlasRelationshipDef employeeManagerType    = new AtlasRelationshipDef(EMPLOYEE_MANAGER_TYPE, description(EMPLOYEE_MANAGER_TYPE),
                                                         DEFAULT_VERSION, AGGREGATION, ONE_TO_TWO,
                                                         new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "manager", SINGLE),
                                                         new AtlasRelationshipEndDef(MANAGER_TYPE, "subordinates", SET, true));
 
-        /******* [Mentor -> Employee] Relationship *******/
-        AtlasRelationshipDef employeeMentorType     = new AtlasRelationshipDef(EMPLOYEE_MENTOR_TYPE, description(EMPLOYEE_MENTOR_TYPE),
+        /******* [Mentors -> Employee] Relationship *******/
+        AtlasRelationshipDef employeeMentorsType    = new AtlasRelationshipDef(EMPLOYEE_MENTORS_TYPE, description(EMPLOYEE_MENTORS_TYPE),
+                                                        DEFAULT_VERSION, AGGREGATION, ONE_TO_TWO,
+                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "mentors", SET),
+                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "mentees", SET, true));
+
+        /******* [Friends -> Employee] Relationship *******/
+        AtlasRelationshipDef employeeFriendsType    = new AtlasRelationshipDef(EMPLOYEE_FRIENDS_TYPE, description(EMPLOYEE_FRIENDS_TYPE),
                                                         DEFAULT_VERSION, ASSOCIATION, ONE_TO_TWO,
-                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "mentor", SINGLE),
-                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "mentees", SET));
+                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "friends", SET),
+                                                        new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "friends", SET));
+
+        /******* [Person -> Sibling] Relationship *******/
+        AtlasRelationshipDef personSiblingType    = new AtlasRelationshipDef(PERSON_SIBLING_TYPE, description(PERSON_SIBLING_TYPE),
+                                                        DEFAULT_VERSION, ASSOCIATION, BOTH,
+                                                        new AtlasRelationshipEndDef(PERSON_TYPE, "sibling", SINGLE),
+                                                        new AtlasRelationshipEndDef(PERSON_TYPE, "sibling", SINGLE));
 
         return new AtlasTypesDef(ImmutableList.of(orgLevelType),
                                  ImmutableList.of(addressType),
                                  ImmutableList.of(securityClearanceType),
                                  ImmutableList.of(personType, employeeType, departmentType, managerType),
-                                 ImmutableList.of(employeeDepartmentType, employeeManagerType, employeeMentorType));
+                                 ImmutableList.of(employeeDepartmentType, employeeManagerType, employeeMentorsType, employeeFriendsType, personSiblingType));
     }
 
     public static AtlasEntitiesWithExtInfo getDepartmentEmployeeInstances() {
@@ -163,25 +176,30 @@ public final class TestRelationshipUtilsV2 {
             johnAddr.setAttribute("street", "Stewart Drive");
             johnAddr.setAttribute("city", "Sunnyvale");
 
-        /******* Manager - Jane (John and Max subordinates) *******/
+        AtlasStruct mikeAddr = new AtlasStruct(ADDRESS_TYPE);
+            mikeAddr.setAttribute("street", "Casa Verde St");
+            mikeAddr.setAttribute("city", "San Jose");
+
+        /******* Manager - Jane (Subordinates: [John, Max]) *******/
         AtlasEntity jane = new AtlasEntity(MANAGER_TYPE);
             jane.setAttribute("name", "Jane");
             jane.setRelationshipAttribute("department", getAtlasObjectId(hrDept));
             jane.setAttribute("address", janeAddr);
 
-        /******* Manager - Julius (no subordinates) *******/
+        /******* Manager - Julius (Subordinates: [], Sibling: Jane) *******/
         AtlasEntity julius = new AtlasEntity(MANAGER_TYPE);
             julius.setAttribute("name", "Julius");
             julius.setRelationshipAttribute("department", getAtlasObjectId(hrDept));
+            julius.setRelationshipAttribute("sibling", getAtlasObjectId(jane));
             julius.setAttribute("address", juliusAddr);
 
-        /******* Employee - Max (Manager: Jane, Mentor: Julius) *******/
+        /******* Employee - Max (Manager: Jane, Mentors: [Julius], Sibling: Julius) *******/
         AtlasEntity max = new AtlasEntity(EMPLOYEE_TYPE);
             max.setAttribute("name", "Max");
             max.setRelationshipAttribute("department", getAtlasObjectId(hrDept));
             max.setAttribute("address", maxAddr);
             max.setRelationshipAttribute("manager", getAtlasObjectId(jane));
-            max.setRelationshipAttribute("mentor", getAtlasObjectId(julius));
+            max.setRelationshipAttribute("mentors", getAtlasObjectIds(julius));
             max.setAttribute("birthday",new Date(1979, 3, 15));
             max.setAttribute("hasPets", true);
             max.setAttribute("age", 36);
@@ -193,13 +211,14 @@ public final class TestRelationshipUtilsV2 {
             max.setAttribute("numberOfStarsEstimate", new BigInteger("1000000000000000000000000000000"));
             max.setAttribute("approximationOfPi", new BigDecimal("3.1415926535897932"));
 
-        /******* Employee - John (Manager: Jane, Mentor: Max) *******/
+        /******* Employee - John (Manager: Jane, Mentors: [Max], Friends: [Max]) *******/
         AtlasEntity john = new AtlasEntity(EMPLOYEE_TYPE);
             john.setAttribute("name", "John");
             john.setRelationshipAttribute("department", getAtlasObjectId(hrDept));
             john.setAttribute("address", johnAddr);
             john.setRelationshipAttribute("manager", getAtlasObjectId(jane));
-            john.setRelationshipAttribute("mentor", getAtlasObjectId(max));
+            john.setRelationshipAttribute("mentors", getAtlasObjectIds(max, julius));
+            john.setRelationshipAttribute("friends", getAtlasObjectIds(max));
             john.setAttribute("birthday",new Date(1950, 5, 15));
             john.setAttribute("hasPets", true);
             john.setAttribute("numberOfCars", 1);
@@ -211,11 +230,30 @@ public final class TestRelationshipUtilsV2 {
             john.setAttribute("numberOfStarsEstimate", new BigInteger("1000000000000000000000"));
             john.setAttribute("approximationOfPi", new BigDecimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286"));
 
+        /******* Employee - Mike (Manager: Julius, Friends: [Max, John]) *******/
+        AtlasEntity mike = new AtlasEntity(EMPLOYEE_TYPE);
+            mike.setAttribute("name", "Mike");
+            mike.setRelationshipAttribute("department", getAtlasObjectId(hrDept));
+            mike.setAttribute("address", mikeAddr);
+            mike.setRelationshipAttribute("manager", getAtlasObjectId(julius));
+            mike.setRelationshipAttribute("friends", getAtlasObjectIds(max, john));
+            mike.setAttribute("birthday",new Date(1947, 8, 15));
+            mike.setAttribute("hasPets", false);
+            mike.setAttribute("numberOfCars", 2);
+            mike.setAttribute("houseNumber", 3737);
+            mike.setAttribute("carMileage", 25000);
+            mike.setAttribute("shares", Long.MIN_VALUE);
+            mike.setAttribute("salary", Double.MIN_VALUE);
+            mike.setAttribute("age", 37);
+            mike.setAttribute("numberOfStarsEstimate", new BigInteger("5000050000050000050005"));
+            mike.setAttribute("approximationOfPi", new BigDecimal("3.14159"));
+
         ret.addEntity(hrDept);
         ret.addEntity(jane);
         ret.addEntity(julius);
         ret.addEntity(max);
         ret.addEntity(john);
+        ret.addEntity(mike);
 
         return ret;
     }
@@ -264,4 +302,16 @@ public final class TestRelationshipUtilsV2 {
     private static ImmutableSet<String> superType(String superTypeName) {
         return StringUtils.isNotEmpty(superTypeName) ? ImmutableSet.of(superTypeName) : ImmutableSet.<String>of();
     }
+
+    private static List<AtlasObjectId> getAtlasObjectIds(AtlasEntity... entities) {
+        List<AtlasObjectId> ret = new ArrayList<>();
+
+        if (ArrayUtils.isNotEmpty(entities)) {
+            for (AtlasEntity entity : entities) {
+                ret.add(getAtlasObjectId(entity));
+            }
+        }
+
+        return ret;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
index 0177f7e..020dd45 100755
--- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
@@ -42,7 +42,6 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
 import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.type.AtlasRelationshipType;
-import org.apache.atlas.type.AtlasStructType;
 import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.typesystem.IReferenceableInstance;
 import org.apache.atlas.typesystem.ITypedInstance;
@@ -86,6 +85,10 @@ import java.util.Set;
 import java.util.Stack;
 import java.util.UUID;
 
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
+
 /**
  * Utility class for graph operations.
  */
@@ -308,7 +311,7 @@ public final class GraphHelper {
 
     //In some cases of parallel APIs, the edge is added, but get edge by label doesn't return the edge. ATLAS-1104
     //So traversing all the edges
-    public Iterator<AtlasEdge> getAdjacentEdgesByLabel(AtlasVertex instanceVertex, AtlasEdgeDirection direction, final String edgeLabel) {
+    public static Iterator<AtlasEdge> getAdjacentEdgesByLabel(AtlasVertex instanceVertex, AtlasEdgeDirection direction, final String edgeLabel) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Finding edges for {} with label {}", string(instanceVertex), edgeLabel);
         }
@@ -348,11 +351,11 @@ public final class GraphHelper {
         return null;
     }
 
-    public Iterator<AtlasEdge> getIncomingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
+    public static Iterator<AtlasEdge> getIncomingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
         return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.IN, edgeLabel);
     }
 
-    public Iterator<AtlasEdge> getOutGoingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
+    public static Iterator<AtlasEdge> getOutGoingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
         return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.OUT, edgeLabel);
     }
 
@@ -361,20 +364,24 @@ public final class GraphHelper {
 
         switch (edgeDirection) {
             case IN:
-                ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.IN);
-                break;
+            ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.IN);
+            break;
 
             case OUT:
+            ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.OUT);
+            break;
+
+            case BOTH:
             default:
-                ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.OUT);
+                ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.BOTH);
                 break;
         }
 
         return ret;
     }
 
-    public Iterator<AtlasEdge> getEdgesForLabel(AtlasVertex vertex, String edgeLabel, AtlasRelationshipEdgeDirection edgeDirection) {
-        Iterator<AtlasEdge> ret;
+    public static Iterator<AtlasEdge> getEdgesForLabel(AtlasVertex vertex, String edgeLabel, AtlasRelationshipEdgeDirection edgeDirection) {
+        Iterator<AtlasEdge> ret = null;
 
         switch (edgeDirection) {
             case IN:
@@ -382,8 +389,11 @@ public final class GraphHelper {
                 break;
 
             case OUT:
-            default:
-                ret = getOutGoingEdgesByLabel(vertex, edgeLabel);
+            ret = getOutGoingEdgesByLabel(vertex, edgeLabel);
+            break;
+
+            case BOTH:
+                ret = getAdjacentEdgesByLabel(vertex, AtlasEdgeDirection.BOTH, edgeLabel);
                 break;
         }
 
@@ -1341,32 +1351,38 @@ public final class GraphHelper {
         return StringUtils.isNotEmpty(edge.getLabel()) ? edgeLabel.startsWith("r:") : false;
     }
 
-    public static AtlasObjectId getReferenceObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection) {
+    public static AtlasObjectId getReferenceObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection,
+                                                     AtlasVertex parentVertex) {
         AtlasObjectId ret = null;
 
-        if (relationshipDirection == AtlasRelationshipEdgeDirection.OUT) {
-            ret = new AtlasObjectId(getGuid(edge.getInVertex()), getTypeName(edge.getInVertex()));
+        if (relationshipDirection == OUT) {
+            ret = getAtlasObjectIdForInVertex(edge);
+
+        } else if (relationshipDirection == IN) {
+            ret = getAtlasObjectIdForOutVertex(edge);
 
-        } else if (relationshipDirection == AtlasRelationshipEdgeDirection.IN) {
-            ret = new AtlasObjectId(getGuid(edge.getOutVertex()), getTypeName(edge.getOutVertex()));
+        } else if (relationshipDirection == BOTH){
+            // since relationship direction is BOTH, edge direction can be inward or outward
+            // compare with parent entity vertex and pick the right reference vertex
+            if (verticesEquals(parentVertex, edge.getOutVertex())) {
+                ret = getAtlasObjectIdForInVertex(edge);
+            } else {
+                ret = getAtlasObjectIdForOutVertex(edge);
+            }
         }
 
         return ret;
     }
 
-    public static AtlasObjectId getCurrentObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection) {
-        String typeName = null;
-        String guid     = null;
-
-        if (relationshipDirection == AtlasRelationshipEdgeDirection.OUT) {
-            typeName = GraphHelper.getTypeName(edge.getOutVertex());
-            guid     = GraphHelper.getGuid(edge.getOutVertex());
+    public static AtlasObjectId getAtlasObjectIdForOutVertex(AtlasEdge edge) {
+        return new AtlasObjectId(getGuid(edge.getOutVertex()), getTypeName(edge.getOutVertex()));
+    }
 
-        } else if (relationshipDirection == AtlasRelationshipEdgeDirection.IN) {
-            typeName = GraphHelper.getTypeName(edge.getInVertex());
-            guid     = GraphHelper.getGuid(edge.getInVertex());
-        }
+    public static AtlasObjectId getAtlasObjectIdForInVertex(AtlasEdge edge) {
+        return new AtlasObjectId(getGuid(edge.getInVertex()), getTypeName(edge.getInVertex()));
+    }
 
-        return new AtlasObjectId(guid, typeName);
+    private static boolean verticesEquals(AtlasVertex vertexA, AtlasVertex vertexB) {
+        return StringUtils.equals(getGuid(vertexB), getGuid(vertexA));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
index 4271376..b0940f6 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
@@ -40,6 +40,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
 import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
 import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,9 +55,13 @@ import java.util.Set;
 import java.util.Stack;
 
 import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
+import static org.apache.atlas.repository.graph.GraphHelper.getAtlasObjectIdForInVertex;
+import static org.apache.atlas.repository.graph.GraphHelper.getAtlasObjectIdForOutVertex;
+import static org.apache.atlas.repository.graph.GraphHelper.getGuid;
 import static org.apache.atlas.repository.graph.GraphHelper.getReferenceObjectId;
 import static org.apache.atlas.repository.graph.GraphHelper.isRelationshipEdge;
 import static org.apache.atlas.repository.graph.GraphHelper.string;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
 
 public abstract class DeleteHandlerV1 {
 
@@ -219,14 +224,14 @@ public abstract class DeleteHandlerV1 {
      * @throws AtlasException
      */
     public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned,
-                                       boolean forceDeleteStructTrait) throws AtlasBaseException {
+                                       boolean forceDeleteStructTrait, AtlasVertex vertex) throws AtlasBaseException {
 
         // default edge direction is outward
-        return deleteEdgeReference(edge, typeCategory, isOwned, forceDeleteStructTrait, AtlasRelationshipEdgeDirection.OUT);
+        return deleteEdgeReference(edge, typeCategory, isOwned, forceDeleteStructTrait, AtlasRelationshipEdgeDirection.OUT, vertex);
     }
 
     public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned, boolean forceDeleteStructTrait,
-                                       AtlasRelationshipEdgeDirection relationshipDirection) throws AtlasBaseException {
+                                       AtlasRelationshipEdgeDirection relationshipDirection, AtlasVertex entityVertex) throws AtlasBaseException {
         LOG.debug("Deleting {}", string(edge));
         boolean forceDelete =
                 (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION) && forceDeleteStructTrait;
@@ -250,7 +255,7 @@ public abstract class DeleteHandlerV1 {
             if (isRelationshipEdge(edge)) {
                 deleteEdge(edge, false);
 
-                AtlasObjectId deletedReferenceObjectId = getReferenceObjectId(edge, relationshipDirection);
+                AtlasObjectId deletedReferenceObjectId = getReferenceObjectId(edge, relationshipDirection, entityVertex);
                 RequestContextV1.get().recordEntityUpdate(deletedReferenceObjectId);
             } else {
                 //legacy case - not a relationship edge
@@ -344,7 +349,7 @@ public abstract class DeleteHandlerV1 {
                         if (edges != null) {
                             while (edges.hasNext()) {
                                 AtlasEdge edge = edges.next();
-                                deleteEdgeReference(edge, elemType.getTypeCategory(), isOwned, false);
+                                deleteEdgeReference(edge, elemType.getTypeCategory(), isOwned, false, instanceVertex);
                             }
                         }
                     }
@@ -377,7 +382,7 @@ public abstract class DeleteHandlerV1 {
         boolean isOwned) throws AtlasBaseException {
         AtlasEdge edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
         if (edge != null) {
-            deleteEdgeReference(edge, typeCategory, isOwned, false);
+            deleteEdgeReference(edge, typeCategory, isOwned, false, outVertex);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
index fbb9858..9700917 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
@@ -51,6 +51,7 @@ import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.atlas.type.AtlasTypeUtil;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.IteratorUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -70,7 +71,9 @@ import static org.apache.atlas.repository.graph.GraphHelper.getTypeName;
 import static org.apache.atlas.repository.graph.GraphHelper.isRelationshipEdge;
 import static org.apache.atlas.repository.graph.GraphHelper.string;
 import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
 import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
 
 @Component
 public class EntityGraphMapper {
@@ -353,7 +356,7 @@ public class EntityGraphMapper {
                 AtlasEdge newEdge = mapStructValue(ctx, context);
 
                 if (currentEdge != null && !currentEdge.equals(newEdge)) {
-                    deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true);
+                    deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true, ctx.getReferringVertex());
                 }
 
                 return newEdge;
@@ -423,7 +426,7 @@ public class EntityGraphMapper {
 
                     //delete old reference
                     deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(),
-                                                      true, ctx.getAttribute().getRelationshipEdgeDirection());
+                                                      true, ctx.getAttribute().getRelationshipEdgeDirection(), ctx.getReferringVertex());
                 }
 
                 return newEdge;
@@ -457,7 +460,7 @@ public class EntityGraphMapper {
                 if (!inverseEdge.equals(newEdge)) {
                     // Disconnect old reference
                     deleteHandler.deleteEdgeReference(inverseEdge, inverseAttribute.getAttributeType().getTypeCategory(),
-                                                      inverseAttribute.isOwnedRef(), true);
+                                                      inverseAttribute.isOwnedRef(), true, inverseVertex);
                 }
                 else {
                     // Edge already exists for this attribute between these vertices.
@@ -675,9 +678,7 @@ public class EntityGraphMapper {
                 Map<String, Object> relationshipAttributes = getRelationshipAttributes(ctx.getValue());
 
                 if (ctx.getCurrentEdge() != null) {
-                    ret = updateRelationship(ctx.getCurrentEdge(), attributeVertex, edgeDirection, relationshipAttributes);
-
-                    recordEntityUpdate(attributeVertex);
+                    ret = updateRelationship(ctx.getCurrentEdge(), entityVertex, attributeVertex, edgeDirection, relationshipAttributes);
 
                 } else {
                     String      relationshipName = graphHelper.getRelationshipDefName(entityVertex, entityType, attributeName);
@@ -805,10 +806,16 @@ public class EntityGraphMapper {
         List           newElements         = (List) ctx.getValue();
         AtlasArrayType arrType             = (AtlasArrayType) attribute.getAttributeType();
         AtlasType      elementType         = arrType.getElementType();
-        List<Object>   currentElements     = getArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexProperty());
         boolean        isReference         = AtlasGraphUtilsV1.isReference(elementType);
         AtlasAttribute inverseRefAttribute = attribute.getInverseRefAttribute();
         List<Object>   newElementsCreated  = new ArrayList<>();
+        List<Object>   currentElements;
+
+        if (isRelationshipAttribute(attribute)) {
+            currentElements = getArrayElementsUsingRelationship(ctx.getReferringVertex(), attribute, elementType);
+        } else {
+            currentElements = getArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexProperty());
+        }
 
         if (CollectionUtils.isNotEmpty(newElements)) {
             for (int index = 0; index < newElements.size(); index++) {
@@ -817,6 +824,7 @@ public class EntityGraphMapper {
                                                                                      ctx.getVertexProperty(), elementType, existingEdge);
 
                 Object newEntry = mapCollectionElementsToVertex(arrCtx, context);
+
                 if (isReference && newEntry instanceof AtlasEdge && inverseRefAttribute != null) {
                     // Update the inverse reference value.
                     AtlasEdge newEdge = (AtlasEdge) newEntry;
@@ -829,7 +837,7 @@ public class EntityGraphMapper {
         }
 
         if (isReference) {
-            List<AtlasEdge> additionalEdges = removeUnusedArrayEntries(attribute, (List) currentElements, (List) newElementsCreated);
+            List<AtlasEdge> additionalEdges = removeUnusedArrayEntries(attribute, (List) currentElements, (List) newElementsCreated, ctx.getReferringVertex());
             newElementsCreated.addAll(additionalEdges);
         }
 
@@ -1048,7 +1056,7 @@ public class EntityGraphMapper {
                 AtlasEdge currentEdge = (AtlasEdge)currentMap.get(currentKey);
 
                 if (!newMap.values().contains(currentEdge)) {
-                    boolean deleted = deleteHandler.deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true);
+                    boolean deleted = deleteHandler.deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true, vertex);
 
                     if (!deleted) {
                         additionalMap.put(currentKey, currentEdge);
@@ -1104,8 +1112,10 @@ public class EntityGraphMapper {
         return newEdge;
     }
 
-    private AtlasEdge updateRelationship(AtlasEdge currentEdge, final AtlasVertex newEntityVertex, AtlasRelationshipEdgeDirection edgeDirection,
-                                         Map<String, Object> relationshipAttributes) throws AtlasBaseException {
+
+    private AtlasEdge updateRelationship(AtlasEdge currentEdge, final AtlasVertex parentEntityVertex, final AtlasVertex newEntityVertex,
+                                         AtlasRelationshipEdgeDirection edgeDirection,  Map<String, Object> relationshipAttributes)
+                                         throws AtlasBaseException {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Updating entity reference using relationship {} for reference attribute {}", getTypeName(newEntityVertex));
         }
@@ -1115,8 +1125,15 @@ public class EntityGraphMapper {
 
         // Max's mentor updated from John to Jane (John.mentee --> Max.mentor)
         // mentor attribute (IN direction), current mentee vertex (John) (OUT vertex)
-        String currentEntityId = (edgeDirection == IN) ? getIdFromVertex(currentEdge.getOutVertex()) :
-                                                         getIdFromVertex(currentEdge.getInVertex());
+        String currentEntityId;
+
+        if (edgeDirection == IN) {
+            currentEntityId = getIdFromOutVertex(currentEdge);
+        } else if (edgeDirection == OUT) {
+            currentEntityId = getIdFromInVertex(currentEdge);
+        } else {
+            currentEntityId = getIdFromBothVertex(currentEdge, parentEntityVertex);
+        }
 
         String    newEntityId = getIdFromVertex(newEntityVertex);
         AtlasEdge ret         = currentEdge;
@@ -1129,8 +1146,17 @@ public class EntityGraphMapper {
                 relationshipName = currentEdge.getLabel();
             }
 
-            ret = (edgeDirection == IN) ? getOrCreateRelationship(newEntityVertex, currentEdge.getInVertex(), relationshipName, relationshipAttributes) :
-                                          getOrCreateRelationship(currentEdge.getOutVertex(), newEntityVertex, relationshipName, relationshipAttributes);
+            if (edgeDirection == IN) {
+                ret = getOrCreateRelationship(newEntityVertex, currentEdge.getInVertex(), relationshipName, relationshipAttributes);
+
+            } else if (edgeDirection == OUT) {
+                ret = getOrCreateRelationship(currentEdge.getOutVertex(), newEntityVertex, relationshipName, relationshipAttributes);
+            } else {
+                ret = getOrCreateRelationship(newEntityVertex, parentEntityVertex, relationshipName, relationshipAttributes);
+            }
+
+            //record entity update on new relationship vertex
+            recordEntityUpdate(newEntityVertex);
         }
 
         return ret;
@@ -1145,6 +1171,21 @@ public class EntityGraphMapper {
         }
     }
 
+    public static List<Object> getArrayElementsUsingRelationship(AtlasVertex vertex, AtlasAttribute attribute, AtlasType elementType) {
+        List<Object> ret = null;
+
+        if (AtlasGraphUtilsV1.isReference(elementType)) {
+
+            AtlasRelationshipEdgeDirection edgeDirection = attribute.getRelationshipEdgeDirection();
+            String                         edgeLabel = attribute.getRelationshipEdgeLabel();
+
+            Iterator<AtlasEdge> edgesForLabel = GraphHelper.getEdgesForLabel(vertex, edgeLabel, edgeDirection);
+
+            ret = IteratorUtils.toList(edgesForLabel);
+        }
+        return ret;
+    }
+
     private AtlasEdge getEdgeAt(List<Object> currentElements, int index, AtlasType elemType) {
         AtlasEdge ret = null;
 
@@ -1158,7 +1199,8 @@ public class EntityGraphMapper {
     }
 
     //Removes unused edges from the old collection, compared to the new collection
-    private List<AtlasEdge> removeUnusedArrayEntries(AtlasAttribute attribute, List<AtlasEdge> currentEntries, List<AtlasEdge> newEntries) throws AtlasBaseException {
+
+    private List<AtlasEdge> removeUnusedArrayEntries(AtlasAttribute attribute, List<AtlasEdge> currentEntries, List<AtlasEdge> newEntries, AtlasVertex entityVertex) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(currentEntries)) {
             AtlasType entryType = ((AtlasArrayType) attribute.getAttributeType()).getElementType();
 
@@ -1170,7 +1212,7 @@ public class EntityGraphMapper {
 
                     for (AtlasEdge edge : edgesToRemove) {
                         boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(),
-                                                                             true, attribute.getRelationshipEdgeDirection());
+                                                                             true, attribute.getRelationshipEdgeDirection(), entityVertex);
 
                         if (!deleted) {
                             additionalElements.add(edge);
@@ -1184,7 +1226,6 @@ public class EntityGraphMapper {
 
         return Collections.emptyList();
     }
-
     private void setArrayElementsProperty(AtlasType elementType, AtlasVertex vertex, String vertexPropertyName, List<Object> values) {
         if (AtlasGraphUtilsV1.isReference(elementType)) {
             GraphHelper.setListPropertyFromElementIds(vertex, vertexPropertyName, (List) values);
@@ -1334,7 +1375,7 @@ public class EntityGraphMapper {
                 String relationshipLabel = GraphHelper.getTraitLabel(entityTypeName, classificationName);
                 AtlasEdge edge = graphHelper.getEdgeForLabel(instanceVertex, relationshipLabel);
                 if (edge != null) {
-                    deleteHandler.deleteEdgeReference(edge, TypeCategory.CLASSIFICATION, false, true);
+                    deleteHandler.deleteEdgeReference(edge, TypeCategory.CLASSIFICATION, false, true, instanceVertex);
 
                     // update the traits in entity once trait removal is successful
                     traitNames.remove(classificationName);
@@ -1433,7 +1474,7 @@ public class EntityGraphMapper {
     private static void compactAttributes(AtlasEntity entity) {
         if (entity != null) {
             Map<String, Object> relationshipAttributes = entity.getRelationshipAttributes();
-            Map<String, Object> attributes             = entity.getAttributes();
+            Map<String, Object> attributes = entity.getAttributes();
 
             if (MapUtils.isNotEmpty(relationshipAttributes) && MapUtils.isNotEmpty(attributes)) {
                 for (String attrName : relationshipAttributes.keySet()) {
@@ -1444,4 +1485,23 @@ public class EntityGraphMapper {
             }
         }
     }
-}
+
+    private String getIdFromInVertex(AtlasEdge edge) {
+        return getIdFromVertex(edge.getInVertex());
+    }
+
+    private String getIdFromOutVertex(AtlasEdge edge) {
+        return getIdFromVertex(edge.getOutVertex());
+    }
+
+    private String getIdFromBothVertex(AtlasEdge currentEdge, AtlasVertex parentEntityVertex) {
+        String parentEntityId  = getIdFromVertex(parentEntityVertex);
+        String currentEntityId = getIdFromVertex(currentEdge.getInVertex());
+
+        if (StringUtils.equals(currentEntityId, parentEntityId)) {
+            currentEntityId = getIdFromOutVertex(currentEdge);
+        }
+
+        return currentEntityId;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
index 4e7aa47..f6aa7bb 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
@@ -72,6 +72,9 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_STRING;
 import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
 import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex;
 import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
 
 
 public final class EntityGraphRetriever {
@@ -683,10 +686,12 @@ public final class EntityGraphRetriever {
         List<AtlasRelatedObjectId> ret   = new ArrayList<>();
         Iterator<AtlasEdge>        edges = null;
 
-        if (attribute.getRelationshipEdgeDirection() == AtlasRelationshipEdgeDirection.IN) {
+        if (attribute.getRelationshipEdgeDirection() == IN) {
             edges = graphHelper.getIncomingEdgesByLabel(entityVertex, attribute.getRelationshipEdgeLabel());
-        } else if (attribute.getRelationshipEdgeDirection() == AtlasRelationshipEdgeDirection.OUT) {
+        } else if (attribute.getRelationshipEdgeDirection() == OUT) {
             edges = graphHelper.getOutGoingEdgesByLabel(entityVertex, attribute.getRelationshipEdgeLabel());
+        } else if (attribute.getRelationshipEdgeDirection() == BOTH) {
+            edges = graphHelper.getAdjacentEdgesByLabel(entityVertex, AtlasEdgeDirection.BOTH, attribute.getRelationshipEdgeLabel());
         }
 
         if (edges != null) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
index 2c31140..109118e 100644
--- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
@@ -20,9 +20,15 @@ package org.apache.atlas.repository.store.graph.v1;
 import com.google.common.collect.ImmutableList;
 import org.apache.atlas.TestModules;
 import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
 import org.testng.annotations.Guice;
 
+import java.util.List;
+
 import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 
 /**
  * Inverse reference update test with {@link HardDeleteHandlerV1}
@@ -51,4 +57,56 @@ public class AtlasRelationshipStoreHardDeleteV1Test extends AtlasRelationshipSto
     protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
         verifyRelationshipAttributeValue(a1, "b", null);
     }
-}
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity max, AtlasEntity julius, AtlasEntity mike, AtlasEntity john) throws Exception {
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 2);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+        assertObjectIdsContains(maxFriendsIds, juliusId);
+
+        // Julius's updated friends: [Max]
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertNotNull(juliusFriendsIds);
+        assertEquals(juliusFriendsIds.size(), 1);
+        assertObjectIdsContains(juliusFriendsIds, maxId);
+
+        // Mike's updated friends: [John]
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 1);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+
+        // John's updated friends: [Max, Mike]
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+    }
+
+    protected void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity julius, AtlasEntity jane, AtlasEntity mike) throws Exception {
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+
+        // Julius sibling updated to Mike
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, mikeId);
+
+        // Mike's sibling is Julius
+        AtlasObjectId mikeSiblingId = toAtlasObjectId(mike.getRelationshipAttribute("sibling"));
+        assertNotNull(mikeSiblingId);
+        assertObjectIdEquals(mikeSiblingId, juliusId);
+
+        // Julius removed from Jane's sibling (hard delete)
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNull(janeSiblingId);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
index 33ef8c0..4faf5ad 100644
--- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
@@ -20,9 +20,14 @@ package org.apache.atlas.repository.store.graph.v1;
 import com.google.common.collect.ImmutableList;
 import org.apache.atlas.TestModules;
 import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
 import org.testng.annotations.Guice;
 
+import java.util.List;
+
 import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
 
 
 /**
@@ -52,4 +57,60 @@ public class AtlasRelationshipStoreSoftDeleteV1Test extends AtlasRelationshipSto
     protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
         verifyRelationshipAttributeValue(a1, "b", b.getGuid());
     }
-}
+
+    @Override
+    protected void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity max, AtlasEntity julius, AtlasEntity mike, AtlasEntity john) throws Exception {
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId maxId    = employeeNameIdMap.get("Max");
+
+        // Max's updated friends: [Julius, John, Mike(soft deleted)]
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 3);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+        assertObjectIdsContains(maxFriendsIds, juliusId);
+        assertObjectIdsContains(maxFriendsIds, mikeId);
+
+        // Julius's updated friends: [Max]
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertNotNull(juliusFriendsIds);
+        assertEquals(juliusFriendsIds.size(), 1);
+        assertObjectIdsContains(juliusFriendsIds, maxId);
+
+        // Mike's updated friends: [John, Max(soft deleted)]
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 2);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+        assertObjectIdsContains(mikeFriendsIds, maxId);
+
+        // John's updated friends: [Max, Mike]
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+    }
+
+    protected void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity julius, AtlasEntity jane, AtlasEntity mike) throws Exception {
+        AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+
+        // Julius sibling updated to Mike
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, mikeId);
+
+        // Mike's sibling is Julius
+        AtlasObjectId mikeSiblingId = toAtlasObjectId(mike.getRelationshipAttribute("sibling"));
+        assertNotNull(mikeSiblingId);
+        assertObjectIdEquals(mikeSiblingId, juliusId);
+
+        // Jane's sibling is still Julius (soft delete)
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNotNull(janeSiblingId);
+        assertObjectIdEquals(janeSiblingId, juliusId);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/f59284ad/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
index a35647d..94cc5b9 100644
--- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
@@ -131,21 +131,24 @@ public abstract class AtlasRelationshipStoreV1Test {
         AtlasObjectId johnId   = employeeNameIdMap.get("John");
         AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
         AtlasObjectId janeId   = employeeNameIdMap.get("Jane");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
 
         AtlasEntity hrDept = getEntityFromStore(hrId.getGuid());
         AtlasEntity max    = getEntityFromStore(maxId.getGuid());
         AtlasEntity john   = getEntityFromStore(johnId.getGuid());
         AtlasEntity julius = getEntityFromStore(juliusId.getGuid());
         AtlasEntity jane   = getEntityFromStore(janeId.getGuid());
+        AtlasEntity mike   = getEntityFromStore(mikeId.getGuid());
 
         // Department relationship attributes
         List<AtlasObjectId> deptEmployees = toAtlasObjectIds(hrDept.getRelationshipAttribute("employees"));
         assertNotNull(deptEmployees);
-        assertEquals(deptEmployees.size(), 4);
+        assertEquals(deptEmployees.size(), 5);
         assertObjectIdsContains(deptEmployees, maxId);
         assertObjectIdsContains(deptEmployees, johnId);
         assertObjectIdsContains(deptEmployees, juliusId);
         assertObjectIdsContains(deptEmployees, janeId);
+        assertObjectIdsContains(deptEmployees, mikeId);
 
         // Max employee validation
         AtlasObjectId maxDepartmentId = toAtlasObjectId(max.getRelationshipAttribute("department"));
@@ -156,15 +159,22 @@ public abstract class AtlasRelationshipStoreV1Test {
         assertNotNull(maxManagerId);
         assertObjectIdEquals(maxManagerId, janeId);
 
-        AtlasObjectId maxMentorId = toAtlasObjectId(max.getRelationshipAttribute("mentor"));
-        assertNotNull(maxMentorId);
-        assertObjectIdEquals(maxMentorId, juliusId);
+        List<AtlasObjectId> maxMentorsId = toAtlasObjectIds(max.getRelationshipAttribute("mentors"));
+        assertNotNull(maxMentorsId);
+        assertEquals(maxMentorsId.size(), 1);
+        assertObjectIdEquals(maxMentorsId.get(0), juliusId);
 
         List<AtlasObjectId> maxMenteesId = toAtlasObjectIds(max.getRelationshipAttribute("mentees"));
         assertNotNull(maxMenteesId);
         assertEquals(maxMenteesId.size(), 1);
         assertObjectIdEquals(maxMenteesId.get(0), johnId);
 
+        List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+        assertNotNull(maxFriendsIds);
+        assertEquals(maxFriendsIds.size(), 2);
+        assertObjectIdsContains(maxFriendsIds, mikeId);
+        assertObjectIdsContains(maxFriendsIds, johnId);
+
         // John Employee validation
         AtlasObjectId johnDepartmentId = toAtlasObjectId(john.getRelationshipAttribute("department"));
         assertNotNull(johnDepartmentId);
@@ -174,13 +184,42 @@ public abstract class AtlasRelationshipStoreV1Test {
         assertNotNull(johnManagerId);
         assertObjectIdEquals(johnManagerId, janeId);
 
-        AtlasObjectId johnMentorId = toAtlasObjectId(john.getRelationshipAttribute("mentor"));
-        assertNotNull(johnMentorId);
-        assertObjectIdEquals(johnMentorId, maxId);
+        List<AtlasObjectId> johnMentorIds = toAtlasObjectIds(john.getRelationshipAttribute("mentors"));
+        assertNotNull(johnMentorIds);
+        assertEquals(johnMentorIds.size(), 2);
+        assertObjectIdsContains(johnMentorIds, maxId);
+        assertObjectIdsContains(johnMentorIds, juliusId);
 
         List<AtlasObjectId> johnMenteesId = toAtlasObjectIds(john.getRelationshipAttribute("mentees"));
         assertEmpty(johnMenteesId);
 
+        List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+        assertNotNull(johnFriendsIds);
+        assertEquals(johnFriendsIds.size(), 2);
+        assertObjectIdsContains(johnFriendsIds, mikeId);
+        assertObjectIdsContains(johnFriendsIds, maxId);
+
+        // Mike Employee validation
+        AtlasObjectId mikeDepartmentId = toAtlasObjectId(mike.getRelationshipAttribute("department"));
+        assertNotNull(mikeDepartmentId);
+        assertObjectIdEquals(mikeDepartmentId, hrId);
+
+        AtlasObjectId mikeManagerId = toAtlasObjectId(mike.getRelationshipAttribute("manager"));
+        assertNotNull(mikeManagerId);
+        assertObjectIdEquals(mikeManagerId, juliusId);
+
+        List<AtlasObjectId> mikeMentorIds = toAtlasObjectIds(mike.getRelationshipAttribute("mentors"));
+        assertEmpty(mikeMentorIds);
+
+        List<AtlasObjectId> mikeMenteesId = toAtlasObjectIds(mike.getRelationshipAttribute("mentees"));
+        assertEmpty(mikeMenteesId);
+
+        List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+        assertNotNull(mikeFriendsIds);
+        assertEquals(mikeFriendsIds.size(), 2);
+        assertObjectIdsContains(mikeFriendsIds, maxId);
+        assertObjectIdsContains(mikeFriendsIds, johnId);
+
         // Jane Manager validation
         AtlasObjectId janeDepartmentId = toAtlasObjectId(jane.getRelationshipAttribute("department"));
         assertNotNull(janeDepartmentId);
@@ -189,8 +228,8 @@ public abstract class AtlasRelationshipStoreV1Test {
         AtlasObjectId janeManagerId = toAtlasObjectId(jane.getRelationshipAttribute("manager"));
         assertNull(janeManagerId);
 
-        AtlasObjectId janeMentorId = toAtlasObjectId(jane.getRelationshipAttribute("mentor"));
-        assertNull(janeMentorId);
+        List<AtlasObjectId> janeMentorIds = toAtlasObjectIds(jane.getRelationshipAttribute("mentors"));
+        assertEmpty(janeMentorIds);
 
         List<AtlasObjectId> janeMenteesId = toAtlasObjectIds(jane.getRelationshipAttribute("mentees"));
         assertEmpty(janeMenteesId);
@@ -201,6 +240,13 @@ public abstract class AtlasRelationshipStoreV1Test {
         assertObjectIdsContains(janeSubordinateIds, maxId);
         assertObjectIdsContains(janeSubordinateIds, johnId);
 
+        List<AtlasObjectId> janeFriendsIds = toAtlasObjectIds(jane.getRelationshipAttribute("friends"));
+        assertEmpty(janeFriendsIds);
+
+        AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+        assertNotNull(janeSiblingId);
+        assertObjectIdEquals(janeSiblingId, juliusId);
+
         // Julius Manager validation
         AtlasObjectId juliusDepartmentId = toAtlasObjectId(julius.getRelationshipAttribute("department"));
         assertNotNull(juliusDepartmentId);
@@ -209,16 +255,26 @@ public abstract class AtlasRelationshipStoreV1Test {
         AtlasObjectId juliusManagerId = toAtlasObjectId(julius.getRelationshipAttribute("manager"));
         assertNull(juliusManagerId);
 
-        AtlasObjectId juliusMentorId = toAtlasObjectId(julius.getRelationshipAttribute("mentor"));
-        assertNull(juliusMentorId);
+        List<AtlasObjectId> juliusMentorIds = toAtlasObjectIds(julius.getRelationshipAttribute("mentors"));
+        assertEmpty(juliusMentorIds);
 
         List<AtlasObjectId> juliusMenteesId = toAtlasObjectIds(julius.getRelationshipAttribute("mentees"));
         assertNotNull(juliusMenteesId);
-        assertEquals(juliusMenteesId.size(), 1);
+        assertEquals(juliusMenteesId.size(), 2);
         assertObjectIdsContains(juliusMenteesId, maxId);
+        assertObjectIdsContains(juliusMenteesId, johnId);
 
         List<AtlasObjectId> juliusSubordinateIds = toAtlasObjectIds(julius.getRelationshipAttribute("subordinates"));
-        assertEmpty(juliusSubordinateIds);
+        assertNotNull(juliusSubordinateIds);
+        assertEquals(juliusSubordinateIds.size(), 1);
+        assertObjectIdsContains(juliusSubordinateIds, mikeId);
+
+        List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+        assertEmpty(juliusFriendsIds);
+
+        AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+        assertNotNull(juliusSiblingId);
+        assertObjectIdEquals(juliusSiblingId, janeId);
     }
 
     @Test
@@ -226,6 +282,8 @@ public abstract class AtlasRelationshipStoreV1Test {
         AtlasObjectId maxId    = employeeNameIdMap.get("Max");
         AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
         AtlasObjectId janeId   = employeeNameIdMap.get("Jane");
+        AtlasObjectId mikeId   = employeeNameIdMap.get("Mike");
+        AtlasObjectId johnId   = employeeNameIdMap.get("John");
 
         // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
         // This should also update Julius to add Max to the inverse Manager.subordinates reference.
@@ -249,9 +307,9 @@ public abstract class AtlasRelationshipStoreV1Test {
         AtlasEntity maxEntity = updatedEntities.getEntity(maxId.getGuid());
         verifyRelationshipAttributeValue(maxEntity, "manager", juliusId.getGuid());
 
-        // Max added to the subordinate list of Julius
+        // Max added to the subordinate list of Julius, existing subordinate is Mike
         AtlasEntity juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
-        verifyRelationshipAttributeList(juliusEntity, "subordinates", ImmutableList.of(maxId));
+        verifyRelationshipAttributeList(juliusEntity, "subordinates", ImmutableList.of(maxId, mikeId));
 
         // Max removed from the subordinate list of Julius
         AtlasEntity janeEntity = updatedEntities.getEntity(janeId.getGuid());
@@ -259,6 +317,48 @@ public abstract class AtlasRelationshipStoreV1Test {
         // Jane's subordinates list includes John and Max for soft delete
         // Jane's subordinates list includes only John for hard delete
         verifyRelationshipAttributeUpdate_NonComposite_OneToMany(janeEntity);
+
+        // Remove Mike from Max's friends list
+        // Max's current friends: [Mike, John]
+        // Max's updated friends: [Julius, John]
+        maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+        maxEntityForUpdate.setRelationshipAttribute("friends", ImmutableList.of(johnId, juliusId));
+
+        init();
+        updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+        partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+        // 3 entities should have been updated:
+        // * Max added Julius and removed Mike from Employee.friends
+        // * Mike removed Max from Employee.friends
+        // * Julius added Max in Employee.friends
+
+        updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), mikeId.getGuid(), johnId.getGuid(), juliusId.getGuid()));
+
+        maxEntity    = updatedEntities.getEntity(maxId.getGuid());
+        juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+        AtlasEntity mikeEntity = updatedEntities.getEntity(mikeId.getGuid());
+        AtlasEntity johnEntity = updatedEntities.getEntity(johnId.getGuid());
+
+        verifyRelationshipAttributeUpdate_ManyToMany_Friends(maxEntity, juliusEntity, mikeEntity, johnEntity);
+
+        // Remove Julius from Jane's sibling and add Mike as new sibling
+        AtlasEntity juliusEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+        juliusEntityForUpdate.setRelationshipAttribute("sibling", mikeId);
+
+        init();
+        updateResponse = entityStore.updateByUniqueAttributes(employeeType, Collections.<String, Object>singletonMap("name", "Julius") , new AtlasEntityWithExtInfo(juliusEntityForUpdate));
+        partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+        assertEquals(partialUpdatedEntities.size(), 3);
+
+        updatedEntities = entityStore.getByIds(ImmutableList.of(juliusId.getGuid(), janeId.getGuid(), mikeId.getGuid()));
+
+        juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+        janeEntity   = updatedEntities.getEntity(janeId.getGuid());
+        mikeEntity   = updatedEntities.getEntity(mikeId.getGuid());
+
+        verifyRelationshipAttributeUpdate_OneToOne_Sibling(juliusEntity, janeEntity, mikeEntity);
     }
 
     @Test
@@ -445,12 +545,16 @@ public abstract class AtlasRelationshipStoreV1Test {
 
     protected abstract void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
 
-    private static void assertObjectIdsContains(List<AtlasObjectId> objectIds, AtlasObjectId objectId) {
+    protected abstract void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3, AtlasEntity e4) throws Exception;
+
+    protected abstract void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3) throws Exception;
+
+    protected static void assertObjectIdsContains(List<AtlasObjectId> objectIds, AtlasObjectId objectId) {
         assertTrue(CollectionUtils.isNotEmpty(objectIds));
         assertTrue(objectIds.contains(objectId));
     }
 
-    private static void assertObjectIdEquals(AtlasObjectId objId1, AtlasObjectId objId2) {
+    protected static void assertObjectIdEquals(AtlasObjectId objId1, AtlasObjectId objId2) {
         assertTrue(objId1.equals(objId2));
     }
 
@@ -458,7 +562,7 @@ public abstract class AtlasRelationshipStoreV1Test {
         assertTrue(collection != null && collection.isEmpty());
     }
 
-    private static List<AtlasObjectId> toAtlasObjectIds(Object object) {
+    protected static List<AtlasObjectId> toAtlasObjectIds(Object object) {
         List<AtlasObjectId> ret = new ArrayList<>();
 
         if (object instanceof List) {
@@ -477,7 +581,7 @@ public abstract class AtlasRelationshipStoreV1Test {
         return ret;
     }
 
-    private static AtlasObjectId toAtlasObjectId(Object object) {
+    protected static AtlasObjectId toAtlasObjectId(Object object) {
         if (object instanceof AtlasRelatedObjectId) {
             AtlasRelatedObjectId relatedObjectId = (AtlasRelatedObjectId) object;
             return new AtlasObjectId(relatedObjectId.getGuid(), relatedObjectId.getTypeName(), relatedObjectId.getUniqueAttributes());