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 2018/01/25 01:01:12 UTC

atlas git commit: ATLAS-2119: Implement update and delete operations for RelationshipREST

Repository: atlas
Updated Branches:
  refs/heads/master 84f4f1035 -> 5900fcb00


ATLAS-2119: Implement update and delete operations for RelationshipREST


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

Branch: refs/heads/master
Commit: 5900fcb001a9a757dc853eb786638601276b7b99
Parents: 84f4f10
Author: Sarath Subramanian <ss...@hortonworks.com>
Authored: Wed Jan 24 16:59:06 2018 -0800
Committer: Sarath Subramanian <ss...@hortonworks.com>
Committed: Wed Jan 24 16:59:06 2018 -0800

----------------------------------------------------------------------
 .../java/org/apache/atlas/AtlasErrorCode.java   |   1 +
 .../atlas/model/instance/AtlasRelationship.java |  68 +++++-----
 .../atlas/repository/graph/GraphHelper.java     |   7 ++
 .../store/graph/v1/AtlasGraphUtilsV1.java       |   4 +
 .../graph/v1/AtlasRelationshipStoreV1.java      | 123 ++++++++++++++++---
 .../store/graph/v1/DeleteHandlerV1.java         |  45 ++++---
 .../store/graph/v1/EntityGraphRetriever.java    |   1 +
 .../graph/v1/AtlasRelationshipStoreV1Test.java  |   2 +-
 8 files changed, 186 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
index f8829b5..3289b48 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -119,6 +119,7 @@ public enum AtlasErrorCode {
     RELATIONSHIP_GUID_NOT_FOUND(404, "ATLAS-404-00-00C", "Given relationship guid {0} is invalid/not found"),
     RELATIONSHIP_CRUD_INVALID_PARAMS(404, "ATLAS-404-00-00D", "Invalid relationship creation/updation parameters passed : {0}"),
     RELATIONSHIPDEF_END_TYPE_NAME_NOT_FOUND(404, "ATLAS-404-00-00E", "RelationshipDef {0} endDef typename {0} cannot be found"),
+    RELATIONSHIP_ALREADY_DELETED(404, "ATLAS-404-00-00F", "Attempting to delete a relationship which is already deleted : {0}"),
 
     // All data conflict errors go here
     TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"),

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/intg/src/main/java/org/apache/atlas/model/instance/AtlasRelationship.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/instance/AtlasRelationship.java b/intg/src/main/java/org/apache/atlas/model/instance/AtlasRelationship.java
index 1f459db..a9912fb 100644
--- a/intg/src/main/java/org/apache/atlas/model/instance/AtlasRelationship.java
+++ b/intg/src/main/java/org/apache/atlas/model/instance/AtlasRelationship.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 
 import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
@@ -49,16 +50,17 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_
 public class AtlasRelationship extends AtlasStruct implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    private String        guid       = null;
-    private AtlasObjectId end1       = null;
-    private AtlasObjectId end2       = null;
-    private String        label      = null;
-    private Status        status     = Status.ACTIVE;
-    private String        createdBy  = null;
-    private String        updatedBy  = null;
-    private Date          createTime = null;
-    private Date          updateTime = null;
-    private Long          version    = 0L;
+    private String        guid          = null;
+    private AtlasObjectId end1          = null;
+    private AtlasObjectId end2          = null;
+    private String        label         = null;
+    private PropagateTags propagateTags = PropagateTags.NONE;
+    private Status        status        = Status.ACTIVE;
+    private String        createdBy     = null;
+    private String        updatedBy     = null;
+    private Date          createTime    = null;
+    private Date          updateTime    = null;
+    private Long          version       = 0L;
 
     public enum Status { ACTIVE, DELETED }
 
@@ -84,13 +86,13 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
     public AtlasRelationship(String typeName, AtlasObjectId end1, AtlasObjectId end2) {
         super(typeName);
 
-        init(nextInternalId(), end1, end2, null, null, null, null, null, null, 0L);
+        init(nextInternalId(), end1, end2, null, null, null, null, null, null, null, 0L);
     }
 
     public AtlasRelationship(String typeName, AtlasObjectId end1, AtlasObjectId end2, Map<String, Object> attributes) {
         super(typeName, attributes);
 
-        init(nextInternalId(), end1, end2, null, null, null, null, null, null, 0L);
+        init(nextInternalId(), end1, end2, null, null, null, null, null, null, null, 0L);
     }
 
     public AtlasRelationship(String typeName, String attrName, Object attrValue) {
@@ -107,8 +109,8 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
         super(other);
 
         if (other != null) {
-            init(other.guid, other.end1, other.end2, other.label, other.status, other.createdBy, other.updatedBy,
-                 other.createTime, other.updateTime, other.version);
+            init(other.guid, other.end1, other.end2, other.label, other.propagateTags, other.status,
+                 other.createdBy, other.updatedBy, other.createTime, other.updateTime, other.version);
         }
     }
 
@@ -180,21 +182,25 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
 
     public void setLabel(String label) { this.label = label; }
 
+    public PropagateTags getPropagateTags() { return propagateTags; }
+
+    public void setPropagateTags(PropagateTags propagateTags) { this.propagateTags = propagateTags; }
+
     private static String nextInternalId() {
         return "-" + Long.toString(s_nextId.getAndIncrement());
     }
 
     private void init() {
-        init(nextInternalId(), null, null, null, null, null, null, null, null, 0L);
+        init(nextInternalId(), null, null, null, null, null,  null, null, null, null, 0L);
     }
 
-    private void init(String guid, AtlasObjectId end1, AtlasObjectId end2, String label,
-                      Status status, String createdBy, String updatedBy,
-                      Date createTime, Date updateTime, Long version) {
+    private void init(String guid, AtlasObjectId end1, AtlasObjectId end2, String label, PropagateTags propagateTags,
+                      Status status, String createdBy, String updatedBy, Date createTime, Date updateTime, Long version) {
         setGuid(guid);
         setEnd1(end1);
         setEnd2(end2);
         setLabel(label);
+        setPropagateTags(propagateTags);
         setStatus(status);
         setCreatedBy(createdBy);
         setUpdatedBy(updatedBy);
@@ -215,6 +221,7 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
         sb.append(", end1=").append(end1);
         sb.append(", end2=").append(end2);
         sb.append(", label='").append(label).append('\'');
+        sb.append(", propagateTags=").append(propagateTags);
         sb.append(", status=").append(status);
         sb.append(", createdBy='").append(createdBy).append('\'');
         sb.append(", updatedBy='").append(updatedBy).append('\'');
@@ -233,22 +240,23 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
         if (!super.equals(o)) { return false; }
 
         AtlasRelationship that = (AtlasRelationship) o;
-        return Objects.equals(guid, that.guid)             &&
-               Objects.equals(end1, that.end1)             &&
-               Objects.equals(end2, that.end2)             &&
-               Objects.equals(label, that.label)           &&
-               status == that.status                       &&
-               Objects.equals(createdBy, that.createdBy)   &&
-               Objects.equals(updatedBy, that.updatedBy)   &&
-               Objects.equals(createTime, that.createTime) &&
-               Objects.equals(updateTime, that.updateTime) &&
-               Objects.equals(version, that.version);
+        return Objects.equals(guid, that.guid) &&
+                Objects.equals(end1, that.end1) &&
+                Objects.equals(end2, that.end2) &&
+                Objects.equals(label, that.label) &&
+                propagateTags == that.propagateTags &&
+                status == that.status &&
+                Objects.equals(createdBy, that.createdBy) &&
+                Objects.equals(updatedBy, that.updatedBy) &&
+                Objects.equals(createTime, that.createTime) &&
+                Objects.equals(updateTime, that.updateTime) &&
+                Objects.equals(version, that.version);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(super.hashCode(), guid, end1, end2, label, status, createdBy,
-                            updatedBy, createTime, updateTime, version);
+        return Objects.hash(super.hashCode(), guid, end1, end2, label, propagateTags,
+                status, createdBy, updatedBy, createTime, updateTime, version);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/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 4da74b9..8c88610 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
@@ -33,6 +33,7 @@ import org.apache.atlas.model.typedef.AtlasRelationshipDef;
 import org.apache.atlas.v1.model.instance.Id;
 import org.apache.atlas.v1.model.instance.Referenceable;
 import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
 import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
 import org.apache.atlas.repository.Constants;
 import org.apache.atlas.repository.RepositoryException;
@@ -722,6 +723,12 @@ public final class GraphHelper {
         return (getState(element) == Id.EntityState.DELETED) ? AtlasRelationship.Status.DELETED : AtlasRelationship.Status.ACTIVE;
     }
 
+    public static PropagateTags getPropagateTags(AtlasElement element) {
+        String propagateTags = element.getProperty(Constants.RELATIONSHIPTYPE_TAG_PROPAGATION_KEY, String.class);
+
+        return (propagateTags == null) ? null : PropagateTags.valueOf(propagateTags);
+    }
+
     //Added conditions in fetching system attributes to handle test failures in GremlinTest where these properties are not set
     public static String getCreatedByAsString(AtlasElement element){
         return element.getProperty(Constants.CREATED_BY_KEY, String.class);

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java
index 37a9661..fdc6024 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java
@@ -103,6 +103,10 @@ public class AtlasGraphUtilsV1 {
         return vertex.getProperty(Constants.GUID_PROPERTY_KEY, String.class);
     }
 
+    public static String getIdFromEdge(AtlasEdge edge) {
+        return edge.getProperty(Constants.GUID_PROPERTY_KEY, String.class);
+    }
+
     public static String getTypeName(AtlasElement element) {
         return element.getProperty(Constants.ENTITY_TYPE_PROPERTY_KEY, String.class);
     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
index 9301cfa..cf414bf 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
@@ -17,6 +17,7 @@
  */
 package org.apache.atlas.repository.store.graph.v1;
 
+import com.google.common.collect.ImmutableSet;
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.annotation.GraphTransaction;
 import org.apache.atlas.exception.AtlasBaseException;
@@ -24,6 +25,7 @@ import org.apache.atlas.model.TypeCategory;
 import org.apache.atlas.model.instance.AtlasObjectId;
 import org.apache.atlas.model.instance.AtlasRelationship;
 import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
 import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
 import org.apache.atlas.repository.Constants;
 import org.apache.atlas.repository.RepositoryException;
@@ -44,6 +46,7 @@ import org.springframework.stereotype.Component;
 
 import javax.inject.Inject;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -52,7 +55,11 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 
+import static org.apache.atlas.model.instance.AtlasEntity.Status.DELETED;
+import static org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags.ONE_TO_TWO;
+import static org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags.TWO_TO_ONE;
 import static org.apache.atlas.repository.graphdb.AtlasEdgeDirection.BOTH;
+import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getState;
 import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getTypeName;
 
 @Component
@@ -62,12 +69,14 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
 
     private final AtlasTypeRegistry    typeRegistry;
     private final EntityGraphRetriever entityRetriever;
+    private final DeleteHandlerV1      deleteHandler;
     private final GraphHelper          graphHelper = GraphHelper.getInstance();
 
     @Inject
-    public AtlasRelationshipStoreV1(AtlasTypeRegistry typeRegistry) {
-        this.typeRegistry    = typeRegistry;
-        this.entityRetriever = new EntityGraphRetriever(typeRegistry);
+    public AtlasRelationshipStoreV1(AtlasTypeRegistry typeRegistry, DeleteHandlerV1 deleteHandler) {
+        this.typeRegistry               = typeRegistry;
+        this.entityRetriever            = new EntityGraphRetriever(typeRegistry);
+        this.deleteHandler              = deleteHandler;
     }
 
     @Override
@@ -97,9 +106,16 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
             LOG.debug("==> update({})", relationship);
         }
 
-        AtlasRelationship ret = null;
+        String guid = relationship.getGuid();
+
+        if (StringUtils.isEmpty(guid)) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_GUID_NOT_FOUND, guid);
+        }
+
+        validateRelationship(relationship);
+
+        AtlasRelationship ret = updateRelationship(relationship);
 
-        // TODO: update(relationship) implementation
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== update({}): {}", relationship, ret);
@@ -135,7 +151,21 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
             LOG.debug("==> deleteById({})", guid);
         }
 
-        // TODO: deleteById(guid) implementation
+        if (StringUtils.isEmpty(guid)) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_CRUD_INVALID_PARAMS, " empty/null guid");
+        }
+
+        AtlasEdge edge = graphHelper.getEdgeForGUID(guid);
+
+        if (edge == null) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_GUID_NOT_FOUND, guid);
+        }
+
+        if (getState(edge) == DELETED) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_ALREADY_DELETED, guid);
+        }
+
+        deleteHandler.deleteRelationships(Collections.singleton(edge));
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== deleteById({}): {}", guid);
@@ -206,6 +236,33 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
         return ret;
     }
 
+    private AtlasRelationship updateRelationship(AtlasRelationship relationship) throws AtlasBaseException {
+        AtlasEdge relationshipEdge = graphHelper.getEdgeForGUID(relationship.getGuid());
+
+        if (relationshipEdge == null) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_GUID_NOT_FOUND, relationship.getGuid());
+        }
+
+        AtlasRelationshipType relationType = typeRegistry.getRelationshipTypeByName(relationship.getTypeName());
+
+        AtlasGraphUtilsV1.setProperty(relationshipEdge, Constants.RELATIONSHIPTYPE_TAG_PROPAGATION_KEY, relationship.getPropagateTags().name());
+
+        if (MapUtils.isNotEmpty(relationType.getAllAttributes())) {
+            for (AtlasAttribute attr : relationType.getAllAttributes().values()) {
+                String attrName           = attr.getName();
+                String attrVertexProperty = attr.getVertexPropertyName();
+
+                if (relationship.hasAttribute(attrName)) {
+                    Object attrValue = relationship.getAttribute(attrName);
+
+                    AtlasGraphUtilsV1.setProperty(relationshipEdge, attrVertexProperty, attrValue);
+                }
+            }
+        }
+
+        return entityRetriever.mapEdgeToAtlasRelationship(relationshipEdge);
+    }
+
     private void validateRelationship(AtlasRelationship relationship) throws AtlasBaseException {
         if (relationship == null) {
             throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "AtlasRelationship is null");
@@ -252,38 +309,44 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
         if (LOG.isDebugEnabled()) {
             LOG.debug("validateEnds entry relationship:" + relationship);
         }
-        List<AtlasObjectId> ends = new ArrayList<>();
-        List<AtlasRelationshipEndDef> endDefs = new ArrayList<>();
-        String relationshipTypeName = relationship.getTypeName();
-        AtlasRelationshipDef relationshipDef = typeRegistry.getRelationshipDefByName(relationshipTypeName);
+        List<AtlasObjectId>           ends                 = new ArrayList<>();
+        List<AtlasRelationshipEndDef> endDefs              = new ArrayList<>();
+        String                        relationshipTypeName = relationship.getTypeName();
+        AtlasRelationshipDef          relationshipDef      = typeRegistry.getRelationshipDefByName(relationshipTypeName);
+
         ends.add(relationship.getEnd1());
         ends.add(relationship.getEnd2());
         endDefs.add(relationshipDef.getEndDef1());
         endDefs.add(relationshipDef.getEndDef2());
 
         for (int i = 0; i < ends.size(); i++) {
-            AtlasObjectId end = ends.get(i);
-            String guid = end.getGuid();
-            String typeName = end.getTypeName();
+            AtlasObjectId       end              = ends.get(i);
+            String              guid             = end.getGuid();
+            String              typeName         = end.getTypeName();
             Map<String, Object> uniqueAttributes = end.getUniqueAttributes();
-            AtlasVertex endVertex = AtlasGraphUtilsV1.findByGuid(guid);
+            AtlasVertex         endVertex        = AtlasGraphUtilsV1.findByGuid(guid);
 
             if (!AtlasTypeUtil.isValidGuid(guid) || endVertex == null) {
                 throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guid);
+
             } else if (MapUtils.isNotEmpty(uniqueAttributes)) {
                 AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
+
                 if (AtlasGraphUtilsV1.findByUniqueAttributes(entityType, uniqueAttributes) == null) {
                     throw new AtlasBaseException(AtlasErrorCode.INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND, typeName, uniqueAttributes.toString());
                 }
             } else {
                 // check whether the guid is the correct type
                 String vertexTypeName = endVertex.getProperty(Constants.TYPE_NAME_PROPERTY_KEY, String.class);
+
                 if (!Objects.equals(vertexTypeName, typeName)) {
                     String attrName = endDefs.get(i).getName();
+
                     throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_INVALID_ENDTYPE, attrName, guid, vertexTypeName, typeName);
                 }
             }
         }
+
         if (LOG.isDebugEnabled()) {
             LOG.debug("validateEnds exit successfully validated relationship:" + relationship);
         }
@@ -350,11 +413,10 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
         return ret;
     }
 
-    private AtlasEdge createRelationshipEdge(AtlasVertex fromVertex, AtlasVertex toVertex, AtlasRelationship relationship)
-                                             throws RepositoryException {
-
-        String    relationshipLabel = getRelationshipEdgeLabel(fromVertex, toVertex, relationship);
-        AtlasEdge ret               = graphHelper.getOrCreateEdge(fromVertex, toVertex, relationshipLabel);
+    private AtlasEdge createRelationshipEdge(AtlasVertex fromVertex, AtlasVertex toVertex, AtlasRelationship relationship) throws RepositoryException {
+        String        relationshipLabel = getRelationshipEdgeLabel(fromVertex, toVertex, relationship);
+        PropagateTags tagPropagation    = getRelationshipTagPropagation(fromVertex, toVertex, relationship);
+        AtlasEdge     ret               = graphHelper.getOrCreateEdge(fromVertex, toVertex, relationshipLabel);
 
         // map additional properties to relationship edge
         if (ret != null) {
@@ -363,6 +425,29 @@ public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
             AtlasGraphUtilsV1.setProperty(ret, Constants.ENTITY_TYPE_PROPERTY_KEY, relationship.getTypeName());
             AtlasGraphUtilsV1.setProperty(ret, Constants.GUID_PROPERTY_KEY, guid);
             AtlasGraphUtilsV1.setProperty(ret, Constants.VERSION_PROPERTY_KEY, getRelationshipVersion(relationship));
+            AtlasGraphUtilsV1.setProperty(ret, Constants.RELATIONSHIPTYPE_TAG_PROPAGATION_KEY, tagPropagation.name());
+        }
+
+        return ret;
+    }
+
+    private PropagateTags getRelationshipTagPropagation(AtlasVertex fromVertex, AtlasVertex toVertex, AtlasRelationship relationship) {
+        AtlasRelationshipType   relationshipType = typeRegistry.getRelationshipTypeByName(relationship.getTypeName());
+        AtlasRelationshipEndDef endDef1          = relationshipType.getRelationshipDef().getEndDef1();
+        AtlasRelationshipEndDef endDef2          = relationshipType.getRelationshipDef().getEndDef2();
+        Set<String>             fromVertexTypes  = getTypeAndAllSuperTypes(getTypeName(fromVertex));
+        Set<String>             toVertexTypes    = getTypeAndAllSuperTypes(getTypeName(toVertex));
+        PropagateTags           ret              = relationshipType.getRelationshipDef().getPropagateTags();
+
+        // relationshipDef is defined as end1 (hive_db) and end2 (hive_table) and tagPropagation = ONE_TO_TWO
+        // relationship edge exists from [hive_table --> hive_db]
+        // swap the tagPropagation property for such cases.
+        if (fromVertexTypes.contains(endDef2.getType()) && toVertexTypes.contains(endDef1.getType())) {
+            if (ret == ONE_TO_TWO) {
+                ret = TWO_TO_ONE;
+            } else if (ret == TWO_TO_ONE) {
+                ret = ONE_TO_TWO;
+            }
         }
 
         return ret;

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/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 b0940f6..e011c78 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,7 +40,6 @@ 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,14 +53,13 @@ import java.util.List;
 import java.util.Set;
 import java.util.Stack;
 
+import static org.apache.atlas.model.instance.AtlasEntity.Status.DELETED;
 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;
+import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromEdge;
+import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getState;
 
 public abstract class DeleteHandlerV1 {
 
@@ -94,9 +92,9 @@ public abstract class DeleteHandlerV1 {
 
         for (AtlasVertex instanceVertex : instanceVertices) {
             String              guid = AtlasGraphUtilsV1.getIdFromVertex(instanceVertex);
-            AtlasEntity.Status state = AtlasGraphUtilsV1.getState(instanceVertex);
+            AtlasEntity.Status state = getState(instanceVertex);
 
-            if (state == AtlasEntity.Status.DELETED) {
+            if (state == DELETED) {
                 LOG.debug("Skipping deletion of {} as it is already deleted", guid);
                 continue;
             }
@@ -128,6 +126,23 @@ public abstract class DeleteHandlerV1 {
     }
 
     /**
+     * Deletes the specified relationship edges.
+     *
+     * @param edges
+     * @throws AtlasBaseException
+     */
+    public void deleteRelationships(Collection<AtlasEdge> edges) throws AtlasBaseException {
+        for (AtlasEdge edge : edges) {
+            if (getState(edge) == DELETED) {
+                LOG.debug("Skipping deletion of {} as it is already deleted", getIdFromEdge(edge));
+                continue;
+            }
+
+            deleteEdge(edge, false);
+        }
+    }
+
+    /**
      * Get the GUIDs and vertices for all composite entities owned/contained by the specified root entity AtlasVertex.
      * The graph is traversed from the root entity through to the leaf nodes of the containment graph.
      *
@@ -142,8 +157,8 @@ public abstract class DeleteHandlerV1 {
         while (vertices.size() > 0) {
             AtlasVertex vertex = vertices.pop();
 
-            AtlasEntity.Status state = AtlasGraphUtilsV1.getState(vertex);
-            if (state == AtlasEntity.Status.DELETED) {
+            AtlasEntity.Status state = getState(vertex);
+            if (state == DELETED) {
                 //If the reference vertex is marked for deletion, skip it
                 continue;
             }
@@ -167,7 +182,7 @@ public abstract class DeleteHandlerV1 {
                 switch (attrType.getTypeCategory()) {
                 case OBJECT_ID_TYPE:
                     AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel);
-                    if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                    if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
                         AtlasVertex compositeVertex = edge.getInVertex();
                         vertices.push(compositeVertex);
                     }
@@ -181,7 +196,7 @@ public abstract class DeleteHandlerV1 {
                     if (edges != null) {
                         while (edges.hasNext()) {
                             edge = edges.next();
-                            if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                            if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
                                 AtlasVertex compositeVertex = edge.getInVertex();
                                 vertices.push(compositeVertex);
                             }
@@ -200,7 +215,7 @@ public abstract class DeleteHandlerV1 {
                         for (String key : keys) {
                             String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, key);
                             edge = graphHelper.getEdgeForLabel(vertex, mapEdgeLabel);
-                            if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                            if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
                                 AtlasVertex compositeVertex = edge.getInVertex();
                                 vertices.push(compositeVertex);
                             }
@@ -429,9 +444,9 @@ public abstract class DeleteHandlerV1 {
         String outId = GraphHelper.getGuid(outVertex);
 
         AtlasObjectId objId = new AtlasObjectId(outId, typeName);
-        AtlasEntity.Status state = AtlasGraphUtilsV1.getState(outVertex);
+        AtlasEntity.Status state = getState(outVertex);
 
-        if (state == AtlasEntity.Status.DELETED || (outId != null && RequestContextV1.get().isDeletedEntity(objId))) {
+        if (state == DELETED || (outId != null && RequestContextV1.get().isDeletedEntity(objId))) {
             //If the reference vertex is marked for deletion, skip updating the reference
             return;
         }
@@ -564,7 +579,7 @@ public abstract class DeleteHandlerV1 {
         LOG.debug("Setting the external references to {} to null(removing edges)", string(instanceVertex));
 
         for (AtlasEdge edge : (Iterable<AtlasEdge>) instanceVertex.getEdges(AtlasEdgeDirection.IN)) {
-            AtlasEntity.Status edgeState = AtlasGraphUtilsV1.getState(edge);
+            AtlasEntity.Status edgeState = getState(edge);
             if (edgeState == AtlasEntity.Status.ACTIVE) {
                 //Delete only the active edge references
                 AtlasAttribute attribute = getAttributeForEdge(edge.getLabel());

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/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 e7cd51a..e9051a6 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
@@ -796,6 +796,7 @@ public final class EntityGraphRetriever {
         relationship.setEnd2(new AtlasObjectId(GraphHelper.getGuid(end2Vertex), GraphHelper.getTypeName(end2Vertex)));
 
         relationship.setLabel(edge.getLabel());
+        relationship.setPropagateTags(GraphHelper.getPropagateTags(edge));
 
         return relationship;
     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5900fcb0/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 b418fef..8de978c 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
@@ -115,7 +115,7 @@ public abstract class AtlasRelationshipStoreV1Test {
     @BeforeTest
     public void init() throws Exception {
         entityStore       = new AtlasEntityStoreV1(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
-        relationshipStore = new AtlasRelationshipStoreV1(typeRegistry);
+        relationshipStore = new AtlasRelationshipStoreV1(typeRegistry, deleteHandler);
 
         RequestContextV1.clear();
         RequestContextV1.get().setUser(TestUtilsV2.TEST_USER);