ATLAS-1891: added RelationshipDef validation during typesystem updates
diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
index 70480df..49ead6e 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -67,7 +67,7 @@
     INVALID_STRUCT_VALUE(400, "ATLAS-400-00-025", "not a valid struct value {0}"),
     INSTANCE_LINEAGE_INVALID_PARAMS(400, "ATLAS-400-00-026", "Invalid lineage query parameters passed {0}: {1}"),
     ATTRIBUTE_UPDATE_NOT_SUPPORTED(400, "ATLAS-400-00-027", "{0}.{1} : attribute update not supported"),
-	INVALID_VALUE(400, "ATLAS-400-00-028", "invalid value: {0}"),
+    INVALID_VALUE(400, "ATLAS-400-00-028", "invalid value: {0}"),
     BAD_REQUEST(400, "ATLAS-400-00-029", "{0}"),
     PARAMETER_PARSING_FAILED(400, "ATLAS-400-00-02A", "Parameter parsing failed at: {0}"),
     MISSING_MANDATORY_ATTRIBUTE(400, "ATLAS-400-00-02B", "Mandatory field {0}.{1} has empty/null value"),
@@ -80,7 +80,13 @@
     RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER(400,  "ATLAS-400-00-033", "COMPOSITION relationshipDef {0} cannot have a SET cardinality and be a container"),
     RELATIONSHIPDEF_LIST_ON_END(400,  "ATLAS-400-00-034", "relationshipDef {0} cannot have a LIST cardinality on an end"),
     RELATIONSHIPDEF_INVALID_END_TYPE(400,  "ATLAS-400-00-035", "relationshipDef {0} has invalid end type {1}"),
-    INVALID_RELATIONSHIP_END_TYPE(400, "ATLAS-400-00-036", "invalid end type for relationship {0}: expected {1}, found {2}"),
+    INVALID_RELATIONSHIP_END_TYPE(400, "ATLAS-400-00-036", "invalid update for relationshipDef {0}: new end type {1}, existing end type {2}"),
+    RELATIONSHIPDEF_INVALID_END1_UPDATE(400, "ATLAS-400-00-037", "invalid update for relationshipDef {0}: new end1 {1}, existing end1 {2}"),
+    RELATIONSHIPDEF_INVALID_END2_UPDATE(400, "ATLAS-400-00-038", "invalid update for relationshipDef {0}: new end2 {1}, existing end2 {2}"),
+    RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE(400, "ATLAS-400-00-039", "invalid  update for relationship {0}: new relationshipDef category {1}, existing relationshipDef category {2}"),
+    RELATIONSHIPDEF_INVALID_NAME_UPDATE(400, "ATLAS-400-00-040", "invalid relationshipDef rename for relationship guid {0}: new name {1}, existing name {2}"),
+    RELATIONSHIPDEF_END1_NAME_INVALID(400, "ATLAS-400-00-020", "{0}: invalid end1 name. Name must not contain query keywords"),
+    RELATIONSHIPDEF_END2_NAME_INVALID(400, "ATLAS-400-00-020", "{0}: invalid end2 name. Name must not contain query keywords"),
     // All Not found enums go here
     TYPE_NAME_NOT_FOUND(404, "ATLAS-404-00-001", "Given typename {0} was invalid"),
     TYPE_GUID_NOT_FOUND(404, "ATLAS-404-00-002", "Given type guid {0} was invalid"),
@@ -94,14 +100,14 @@
     INSTANCE_NOT_FOUND(404, "ATLAS-404-00-00B", "Given instance is invalid/not found: {0}"),
     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}"),
-
-     // All data conflict errors go here
+    // All data conflict errors go here
     TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"),
     TYPE_HAS_REFERENCES(409, "ATLAS-409-00-002", "Given type {0} has references"),
     INSTANCE_ALREADY_EXISTS(409, "ATLAS-409-00-003", "failed to update entity: {0}"),
     RELATIONSHIP_ALREADY_EXISTS(409, "ATLAS-409-00-004", "relationship {0} already exists between entities {1} and {2}"),
+    TYPE_HAS_RELATIONSHIPS(409, "ATLAS-409-00-005", "Given type {0} has associated relationshipDefs"),
 
-     // All internal errors go here
+    // All internal errors go here
     INTERNAL_ERROR(500, "ATLAS-500-00-001", "Internal server error {0}"),
     INDEX_CREATION_FAILED(500, "ATLAS-500-00-002", "Index creation failed for {0}"),
     INDEX_ROLLBACK_FAILED(500, "ATLAS-500-00-003", "Index rollback failed for {0}"),
@@ -155,4 +161,4 @@
     public String getErrorCode() {
         return errorCode;
     }
-}
+}
\ No newline at end of file
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java
index 3125668..3f39541 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java
@@ -23,6 +23,8 @@
 import org.apache.atlas.model.instance.AtlasObjectId;
 import org.apache.atlas.model.typedef.*;
 import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
@@ -241,6 +243,18 @@
         return new AtlasEntityDef(name, description, version, Arrays.asList(attrDefs), superTypes);
     }
 
+    public static AtlasRelationshipDef createRelationshipTypeDef(String                  name,
+                                                                 String                  description,
+                                                                 String                  version,
+                                                                 RelationshipCategory    relationshipCategory,
+                                                                 PropagateTags           propagateTags,
+                                                                 AtlasRelationshipEndDef endDef1,
+                                                                 AtlasRelationshipEndDef endDef2,
+                                                                 AtlasAttributeDef...    attrDefs) {
+        return new AtlasRelationshipDef(name, description, version, relationshipCategory, propagateTags,
+                                        endDef1, endDef2, Arrays.asList(attrDefs));
+    }
+
     public static AtlasTypesDef getTypesDef(List<AtlasEnumDef> enums,
         List<AtlasStructDef> structs,
         List<AtlasClassificationDef> traits,
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java
index aefd168..9d9c59d 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java
@@ -412,11 +412,12 @@
         AtlasTypesDef ret = updateGraphStore(typesDef, ttr);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("<== AtlasTypeDefGraphStore.updateTypesDef(enums={}, structs={}, classfications={}, entities={})",
+            LOG.debug("<== AtlasTypeDefGraphStore.updateTypesDef(enums={}, structs={}, classfications={}, entities={}, relationships={})",
                     CollectionUtils.size(typesDef.getEnumDefs()),
                     CollectionUtils.size(typesDef.getStructDefs()),
                     CollectionUtils.size(typesDef.getClassificationDefs()),
-                    CollectionUtils.size(typesDef.getEntityDefs()));
+                    CollectionUtils.size(typesDef.getEntityDefs()),
+                    CollectionUtils.size(typesDef.getRelationshipDefs()));
         }
 
         return ret;
@@ -857,6 +858,7 @@
         AtlasStructDefStore         structDefStore   = getStructDefStore(ttr);
         AtlasClassificationDefStore classifiDefStore = getClassificationDefStore(ttr);
         AtlasEntityDefStore         entityDefStore   = getEntityDefStore(ttr);
+        AtlasRelationshipDefStore   relationDefStore = getRelationshipDefStore(ttr);
 
         if (CollectionUtils.isNotEmpty(typesDef.getEnumDefs())) {
             for (AtlasEnumDef enumDef : typesDef.getEnumDefs()) {
@@ -882,6 +884,12 @@
             }
         }
 
+        if (CollectionUtils.isNotEmpty(typesDef.getRelationshipDefs())) {
+            for (AtlasRelationshipDef relationshipDef : typesDef.getRelationshipDefs()) {
+                ret.getRelationshipDefs().add(relationDefStore.update(relationshipDef));
+            }
+        }
+
         return ret;
     }
 
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java
index 8046234..d6cb2fd 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java
@@ -265,6 +265,11 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
         }
 
+        // error if we are trying to delete an entityDef that has a relationshipDef
+        if (typeDefStore.hasIncomingEdgesWithLabel(ret, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL)){
+            throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_RELATIONSHIPS, name);
+        }
+
         typeDefStore.deleteTypeVertexOutEdges(ret);
 
         if (LOG.isDebugEnabled()) {
@@ -313,6 +318,11 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
         }
 
+        // error if we are trying to delete an entityDef that has a relationshipDef
+        if (typeDefStore.hasIncomingEdgesWithLabel(ret, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL)){
+            throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_RELATIONSHIPS, typeName);
+        }
+
         typeDefStore.deleteTypeVertexOutEdges(ret);
 
         if (LOG.isDebugEnabled()) {
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 00fe94b..42bd58f 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
@@ -50,6 +50,7 @@
     public static final String PROPERTY_PREFIX      = Constants.INTERNAL_PROPERTY_KEY_PREFIX + "type.";
     public static final String SUPERTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".supertype";
     public static final String VERTEX_TYPE          = "typeSystem";
+    public static final String RELATIONSHIPTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".relationshipType";
 
 
     public static String getTypeDefPropertyKey(AtlasBaseTypeDef typeDef) {
@@ -289,6 +290,22 @@
         return vertex;
     }
 
+    public static boolean relationshipTypeHasInstanceEdges(String typeName) throws AtlasBaseException {
+        AtlasGraphQuery query = AtlasGraphProvider.getGraphInstance()
+                .query()
+                .has(Constants.TYPE_NAME_PROPERTY_KEY, AtlasGraphQuery.ComparisionOperator.EQUAL, typeName);
+
+        Iterator<AtlasEdge> results = query.edges().iterator();
+
+        boolean hasInstanceEdges = results != null && results.hasNext();
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("relationshipType {} has instance edges {}", typeName, hasInstanceEdges);
+        }
+
+        return hasInstanceEdges;
+    }
+
     private static String toString(AtlasElement element) {
         if (element instanceof AtlasVertex) {
             return toString((AtlasVertex) element);
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java
index 6992e22..194c546 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java
@@ -17,13 +17,17 @@
  */
 package org.apache.atlas.repository.store.graph.v1;
 
+import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.typedef.AtlasRelationshipDef;
 import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory;
 import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
 import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
+import org.apache.atlas.query.QueryParser;
 import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
 import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.AtlasRelationshipDefStore;
 import org.apache.atlas.type.AtlasRelationshipType;
@@ -34,6 +38,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.inject.Inject;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -44,6 +49,7 @@
 public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 implements AtlasRelationshipDefStore {
     private static final Logger LOG = LoggerFactory.getLogger(AtlasRelationshipDefStoreV1.class);
 
+    @Inject
     public AtlasRelationshipDefStoreV1(AtlasTypeDefGraphStoreV1 typeDefStore, AtlasTypeRegistry typeRegistry) {
         super(typeDefStore, typeRegistry);
     }
@@ -62,21 +68,51 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_MATCH_FAILED, relationshipDef.getName(), TypeCategory.RELATIONSHIP.name());
         }
 
-        AtlasVertex ret = typeDefStore.findTypeVertexByName(relationshipDef.getName());
+        AtlasVertex relationshipDefVertex = typeDefStore.findTypeVertexByName(relationshipDef.getName());
 
-        if (ret != null) {
+        if (relationshipDefVertex != null) {
             throw new AtlasBaseException(AtlasErrorCode.TYPE_ALREADY_EXISTS, relationshipDef.getName());
         }
 
-        ret = typeDefStore.createTypeVertex(relationshipDef);
+        relationshipDefVertex = typeDefStore.createTypeVertex(relationshipDef);
 
-        updateVertexPreCreate(relationshipDef, (AtlasRelationshipType) type, ret);
+        updateVertexPreCreate(relationshipDef, (AtlasRelationshipType) type, relationshipDefVertex);
 
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("<== AtlasRelationshipDefStoreV1.preCreate({}): {}", relationshipDef, ret);
+        final AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1();
+        final String type1 = endDef1.getType();
+        final AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2();
+        final String type2 = endDef2.getType();
+        final String name1 = endDef1.getName();
+        final String name2 = endDef2.getName();
+
+        AtlasVertex end1TypeVertex = typeDefStore.findTypeVertexByName(type1);
+
+        AtlasVertex end2TypeVertex = typeDefStore.findTypeVertexByName(type2);
+        // create an edge between the relationshipDef and each of the entityDef vertices.
+        AtlasEdge edge1 = typeDefStore.getOrCreateEdge(relationshipDefVertex, end1TypeVertex, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL);
+
+        /*
+        Where edge1 and edge2 have the same names and types we do not need a second edge.
+        We are not invoking the equals method on the AtlasRelationshipedDef, as we only want 1 edge even if propagateTags or other properties are different.
+        */
+
+        if (!type1.equals(type2) && name1.equals(name2)) {
+            AtlasEdge edge2 = typeDefStore.getOrCreateEdge(relationshipDefVertex, end2TypeVertex, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL);
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("AtlasRelationshipDefStoreV1.preCreate({}): created relationshipDef vertex {}," +
+                          " edge1 as {}, edge2 as {} ", relationshipDef, relationshipDefVertex, edge1, edge2);
+            }
+        } else {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("AtlasRelationshipDefStoreV1.preCreate({}): created relationshipDef vertex {}," +
+                          " and one edge as {} , because end1 and and end2 has same type and name", relationshipDef, relationshipDefVertex, edge1);
+            }
         }
 
-        return ret;
+        LOG.debug("<== AtlasRelationshipDefStoreV1.preCreate({}): {}", relationshipDef, relationshipDefVertex);
+
+        return relationshipDefVertex;
     }
 
     @Override
@@ -207,7 +243,7 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
         }
 
-        updateVertexPreUpdate(relationshipDef, (AtlasRelationshipType) type, vertex);
+        preUpdateCheck(relationshipDef, (AtlasRelationshipType) type, vertex);
 
         AtlasRelationshipDef ret = toRelationshipDef(vertex);
 
@@ -239,8 +275,9 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid);
         }
 
-        updateVertexPreUpdate(relationshipDef, (AtlasRelationshipType) type, vertex);
-        // TODO delete / create edges to entitytypes
+        preUpdateCheck(relationshipDef, (AtlasRelationshipType) type, vertex);
+        // updates should not effect the edges between the types as we do not allow updates that change the endpoints.
+
         AtlasRelationshipDef ret = toRelationshipDef(vertex);
 
         if (LOG.isDebugEnabled()) {
@@ -262,11 +299,11 @@
             throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name);
         }
 
-        if (AtlasGraphUtilsV1.typeHasInstanceVertex(name)) {
+        if (AtlasGraphUtilsV1.relationshipTypeHasInstanceEdges(name)) {
             throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, name);
         }
 
-        // TODO delete the edges to the other types
+        typeDefStore.deleteTypeVertexOutEdges(ret);
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== AtlasRelationshipDefStoreV1.preDeleteByName({}): {}", name, ret);
@@ -310,11 +347,11 @@
 
         String typeName = AtlasGraphUtilsV1.getProperty(ret, Constants.TYPENAME_PROPERTY_KEY, String.class);
 
-        if (AtlasGraphUtilsV1.typeHasInstanceVertex(typeName)) {
+        if (AtlasGraphUtilsV1.relationshipTypeHasInstanceEdges(typeName)) {
             throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, typeName);
         }
 
-        // TODO delete the edges to the other types
+        typeDefStore.deleteTypeVertexOutEdges(ret);
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== AtlasRelationshipDefStoreV1.preDeleteByGuid({}): {}", guid, ret);
@@ -346,18 +383,91 @@
 
     private void updateVertexPreCreate(AtlasRelationshipDef relationshipDef, AtlasRelationshipType relationshipType,
                                        AtlasVertex vertex) throws AtlasBaseException {
+        AtlasRelationshipEndDef end1 = relationshipDef.getEndDef1();
+        AtlasRelationshipEndDef end2 = relationshipDef.getEndDef2();
+
+        // check whether the names added on the relationship Ends are reserved if required.
+        final boolean allowReservedKeywords;
+        try {
+            allowReservedKeywords = ApplicationProperties.get().getBoolean(ALLOW_RESERVED_KEYWORDS, true);
+        } catch (AtlasException e) {
+            throw new AtlasBaseException(e);
+        }
+
+        if (!allowReservedKeywords) {
+            if (QueryParser.isKeyword(end1.getName())) {
+                throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_END1_NAME_INVALID, end1.getName());
+            }
+
+            if (QueryParser.isKeyword(end2.getName())) {
+                throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_END2_NAME_INVALID, end2.getName());
+            }
+        }
+
         AtlasStructDefStoreV1.updateVertexPreCreate(relationshipDef, relationshipType, vertex, typeDefStore);
         // Update ends
-        vertex.setProperty(Constants.RELATIONSHIPTYPE_END1_KEY, AtlasType.toJson(relationshipDef.getEndDef1()));
-        vertex.setProperty(Constants.RELATIONSHIPTYPE_END2_KEY, AtlasType.toJson(relationshipDef.getEndDef2()));
-        // Update RelationshipCategory
-        vertex.setProperty(Constants.RELATIONSHIPTYPE_CATEGORY_KEY, relationshipDef.getRelationshipCategory().name());
-        vertex.setProperty(Constants.RELATIONSHIPTYPE_TAG_PROPAGATION_KEY, relationshipDef.getPropagateTags().name());
+        setVertexPropertiesFromRelationshipDef(relationshipDef, vertex);
     }
 
-    private void updateVertexPreUpdate(AtlasRelationshipDef relationshipDef, AtlasRelationshipType relationshipType,
-                                       AtlasVertex vertex) throws AtlasBaseException {
-        AtlasStructDefStoreV1.updateVertexPreUpdate(relationshipDef, relationshipType, vertex, typeDefStore);
+    private void preUpdateCheck(AtlasRelationshipDef newRelationshipDef, AtlasRelationshipType relationshipType,
+                                AtlasVertex vertex) throws AtlasBaseException {
+        // We will not support an update to endpoints or category key
+        AtlasRelationshipDef existingRelationshipDef = toRelationshipDef(vertex);
+
+        preUpdateCheck(newRelationshipDef, existingRelationshipDef);
+        // we do allow change to tag propagation and the addition of new attributes.
+
+        AtlasStructDefStoreV1.updateVertexPreUpdate(newRelationshipDef, relationshipType, vertex, typeDefStore);
+
+        setVertexPropertiesFromRelationshipDef(newRelationshipDef, vertex);
+    }
+
+    /**
+     * Check ends are the same and relationshipCategory is the same.
+     *
+     * We do this by comparing 2 relationshipDefs to avoid exposing the AtlasVertex to unit testing.
+     *
+     * @param newRelationshipDef
+     * @param existingRelationshipDef
+     * @throws AtlasBaseException
+     */
+    public static void preUpdateCheck(AtlasRelationshipDef newRelationshipDef, AtlasRelationshipDef existingRelationshipDef) throws AtlasBaseException {
+        // do not allow renames of the Def.
+        String existingName = existingRelationshipDef.getName();
+        String newName      = newRelationshipDef.getName();
+
+        if (!existingName.equals(newName)) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_NAME_UPDATE,
+                    newRelationshipDef.getGuid(),existingName, newName);
+        }
+
+        RelationshipCategory existingRelationshipCategory = existingRelationshipDef.getRelationshipCategory();
+        RelationshipCategory newRelationshipCategory      = newRelationshipDef.getRelationshipCategory();
+
+        if ( !existingRelationshipCategory.equals(newRelationshipCategory)){
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE,
+                    newRelationshipDef.getName(),newRelationshipCategory.name(),
+                    existingRelationshipCategory.name() );
+        }
+
+        AtlasRelationshipEndDef existingEnd1 = existingRelationshipDef.getEndDef1();
+        AtlasRelationshipEndDef newEnd1      = newRelationshipDef.getEndDef1();
+
+        if ( !newEnd1.equals(existingEnd1) ) {
+            throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END1_UPDATE,
+                                         newRelationshipDef.getName(), newEnd1.toString(), existingEnd1.toString());
+        }
+
+        AtlasRelationshipEndDef existingEnd2 = existingRelationshipDef.getEndDef2();
+        AtlasRelationshipEndDef newEnd2      = newRelationshipDef.getEndDef2();
+
+        if ( !newEnd2.equals(existingEnd2) ) {
+                throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END2_UPDATE,
+                                         newRelationshipDef.getName(), newEnd2.toString(), existingEnd2.toString());
+        }
+    }
+
+    public static void setVertexPropertiesFromRelationshipDef(AtlasRelationshipDef relationshipDef, AtlasVertex vertex) {
         vertex.setProperty(Constants.RELATIONSHIPTYPE_END1_KEY, AtlasType.toJson(relationshipDef.getEndDef1()));
         vertex.setProperty(Constants.RELATIONSHIPTYPE_END2_KEY, AtlasType.toJson(relationshipDef.getEndDef2()));
         // Update RelationshipCategory
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java
index 2ba4144..6037d43 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java
@@ -242,6 +242,28 @@
         }
     }
 
+    /**
+     * Look to see if there are any IN edges with the supplied label
+     * @param vertex
+     * @param label
+     * @return
+     * @throws AtlasBaseException
+     */
+    boolean hasIncomingEdgesWithLabel(AtlasVertex vertex, String label) throws AtlasBaseException {
+        boolean foundEdges = false;
+        Iterator<AtlasEdge> inEdges = vertex.getEdges(AtlasEdgeDirection.IN).iterator();
+
+        while (inEdges.hasNext()) {
+            AtlasEdge edge = inEdges.next();
+
+            if (label.equals(edge.getLabel())) {
+                foundEdges = true;
+                break;
+            }
+        }
+        return foundEdges;
+    }
+
     void deleteTypeVertex(AtlasVertex vertex) throws AtlasBaseException {
         Iterator<AtlasEdge> inEdges = vertex.getEdges(AtlasEdgeDirection.IN).iterator();
 
diff --git a/repository/src/test/java/org/apache/atlas/TestModules.java b/repository/src/test/java/org/apache/atlas/TestModules.java
index d28956d..fa2ac0d 100644
--- a/repository/src/test/java/org/apache/atlas/TestModules.java
+++ b/repository/src/test/java/org/apache/atlas/TestModules.java
@@ -47,16 +47,9 @@
 import org.apache.atlas.repository.impexp.ExportService;
 import org.apache.atlas.repository.store.graph.AtlasEntityDefStore;
 import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.repository.store.graph.AtlasRelationshipDefStore;
 import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
-import org.apache.atlas.repository.store.graph.v1.AtlasEntityChangeNotifier;
-import org.apache.atlas.repository.store.graph.v1.AtlasEntityDefStoreV1;
-import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1;
-import org.apache.atlas.repository.store.graph.v1.AtlasRelationshipStoreV1;
-import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1;
-import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
-import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper;
-import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1;
-import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
+import org.apache.atlas.repository.store.graph.v1.*;
 import org.apache.atlas.repository.typestore.GraphBackedTypeStore;
 import org.apache.atlas.repository.typestore.ITypeStore;
 import org.apache.atlas.repository.typestore.StoreBackedTypeCache;
@@ -136,6 +129,7 @@
 
             //For testing
             bind(AtlasEntityDefStore.class).to(AtlasEntityDefStoreV1.class).asEagerSingleton();
+            bind(AtlasRelationshipDefStore.class).to(AtlasRelationshipDefStoreV1.class).asEagerSingleton();
             bind(AtlasTypeRegistry.class).asEagerSingleton();
             bind(EntityGraphMapper.class).asEagerSingleton();
             bind(ExportService.class).asEagerSingleton();
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java
new file mode 100644
index 0000000..00d4977
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java
@@ -0,0 +1,332 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph;
+
+import com.google.inject.Inject;
+import org.apache.atlas.ApplicationProperties;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.exception.AtlasBaseException;
+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.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.store.graph.v1.AtlasAbstractDefStoreV1;
+import org.apache.atlas.repository.store.graph.v1.AtlasRelationshipDefStoreV1;
+import org.apache.atlas.type.AtlasTypeUtil;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.fail;
+
+/**
+ * Tests for AtlasRelationshipStoreV1
+ */
+@Guice(modules = TestModules.TestOnlyModule.class)
+public class AtlasRelationshipDefStoreV1Test {
+
+    @Inject
+    private
+    AtlasRelationshipDefStore relationshipDefStore;
+
+    @DataProvider
+    public Object[][] invalidAttributeNameWithReservedKeywords(){
+        AtlasRelationshipDef invalidAttrNameType =
+            AtlasTypeUtil.createRelationshipTypeDef("Invalid_Attribute_Type", "description","" ,
+                    AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                    AtlasRelationshipDef.PropagateTags.BOTH,
+                    new AtlasRelationshipEndDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                    new AtlasRelationshipEndDef("typeB", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                    AtlasTypeUtil.createRequiredAttrDef("order", "string"),
+                    AtlasTypeUtil.createRequiredAttrDef("limit", "string"));
+
+        return new Object[][] {{
+            invalidAttrNameType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateValidProperties(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","0" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.ONE_TO_TWO,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType",
+                        "description1", // updated
+                        "1" , // updated
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH, // updated
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+
+
+    @DataProvider
+    public Object[][] updateRename(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType2", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateRelCat(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef newType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.AGGREGATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][] {{
+                existingType,
+                newType
+        }};
+    }
+    @DataProvider
+    public Object[][] updateEnd1(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeAttr =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeCardinality =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][]{
+                {
+                        existingType,
+                        changeType
+                },
+                {
+                        existingType,
+                        changeAttr
+                },
+                {
+                        existingType,
+                        changeCardinality
+                }
+        };
+    }
+    @DataProvider
+    public Object[][] updateEnd2(){
+        AtlasRelationshipDef existingType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+        AtlasRelationshipDef changeType =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeAttr =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+        AtlasRelationshipDef changeCardinality =
+                AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" ,
+                        AtlasRelationshipDef.RelationshipCategory.ASSOCIATION,
+                        AtlasRelationshipDef.PropagateTags.BOTH,
+                        new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE),
+                        new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST),
+
+                        AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"),
+                        AtlasTypeUtil.createRequiredAttrDef("bbbb", "string"));
+
+
+        return new Object[][]{
+                {
+                        existingType,
+                        changeType
+                },
+                {
+                        existingType,
+                        changeAttr
+                },
+                {
+                        existingType,
+                        changeCardinality
+                }
+        };
+    }
+
+    @Test(dataProvider = "invalidAttributeNameWithReservedKeywords")
+    public void testCreateTypeWithReservedKeywords(AtlasRelationshipDef atlasRelationshipDef) throws AtlasException {
+        try {
+            ApplicationProperties.get().setProperty(AtlasAbstractDefStoreV1.ALLOW_RESERVED_KEYWORDS, false);
+            relationshipDefStore.create(atlasRelationshipDef, null);
+        } catch (AtlasBaseException e) {
+            Assert.assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.ATTRIBUTE_NAME_INVALID);
+        }
+    }
+
+    @Test(dataProvider = "updateValidProperties")
+    public void testupdateVertexPreUpdatepropagateTags(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) throws AtlasBaseException {
+        AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+    }
+
+    @Test(dataProvider = "updateRename")
+    public void testupdateVertexPreUpdateRename(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_NAME_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @Test(dataProvider = "updateRelCat")
+    public void testupdateVertexPreUpdateRelcat(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @Test(dataProvider = "updateEnd1")
+    public void testupdateVertexPreUpdateEnd1(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END1_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+
+    @Test(dataProvider = "updateEnd2")
+    public void testupdateVertexPreUpdateEnd2(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef)  {
+
+        try {
+            AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef);
+            fail("expected error");
+        } catch (AtlasBaseException e) {
+            if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END2_UPDATE)){
+                fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode());
+            }
+        }
+    }
+    @AfterClass
+    public void clear(){
+        AtlasGraphProvider.cleanup();
+    }
+}
diff --git a/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java b/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java
deleted file mode 100644
index 82d6f2e..0000000
--- a/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.atlas.examples;
-
-import java.io.Console;
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-
-import org.apache.atlas.ApplicationProperties;
-import org.apache.atlas.AtlasBaseClient;
-import org.apache.atlas.AtlasClientV2;
-import org.apache.atlas.AtlasException;
-import org.apache.atlas.model.typedef.AtlasTypesDef;
-import org.apache.atlas.type.AtlasType;
-import org.apache.atlas.utils.AuthenticationUtil;
-import org.apache.commons.configuration.Configuration;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/**
- * A driver that sets up types supplied in a file.  
- */
-public class CreateTypesFromJsonFileUtil  extends AtlasBaseClient{
-    public static final String ATLAS_REST_ADDRESS = "atlas.rest.address";
-
-    public static void main(String[] args) throws Exception {
-
-        Console console = System.console();
-        if (console == null) {
-            System.err.println("No console.");
-            System.exit(1);
-        }
-        String[] basicAuthUsernamePassword = null;
-        if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
-            basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput();
-        }
-        AtlasClientV2 atlasClientV2 = getAtlasClientV2(args, basicAuthUsernamePassword);
-
-
-        String createFileName = console.readLine("Enter fileName containing TypeDefs for create:- ");
-        File createFile = new File(createFileName);
-        String createJsonStr = new String( Files.readAllBytes(createFile.toPath()), StandardCharsets.UTF_8);
-
-        System.err.println("create json is :\n" + createJsonStr);
-
-        runTypeCreation(createJsonStr,atlasClientV2);
-//        String updateFileName = console.readLine("Enter fileName containing TypeDefs for update:- ");
-//        File updateFile = new File(updateFileName);
-//        String updateJsonStr = new String( Files.readAllBytes(updateFile.toPath()), StandardCharsets.UTF_8);
-//        System.err.println("update json is :\n" + updateJsonStr);
-//        runTypeUpdate(updateJsonStr,atlasClientV2);
-    }
-
-    @VisibleForTesting
-    static void runTypeCreation(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception {
-        AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
-        atlasClientV2.createAtlasTypeDefs(typesDef);
-    }
-    @VisibleForTesting
-    static void runTypeUpdate(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception {
-        AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
-        atlasClientV2.updateAtlasTypeDefs(typesDef);
-    }
-
-    private static AtlasClientV2 getAtlasClientV2(String[] args, String[] basicAuthUsernamePassword) throws AtlasException {
-        String[] urls = getServerUrl(args);
-
-        AtlasClientV2 atlasClientV2;
-
-        if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
-            atlasClientV2 =new AtlasClientV2(urls,basicAuthUsernamePassword);
-        } else {
-            atlasClientV2 = new AtlasClientV2(urls);
-        }
-        return atlasClientV2;
-    }
-
-    static String[] getServerUrl(String[] args) throws AtlasException {
-        if (args.length > 0) {
-            return args[0].split(",");
-        }
-
-        Configuration configuration = ApplicationProperties.get();
-        String[] urls = configuration.getStringArray(ATLAS_REST_ADDRESS);
-        if (urls == null || urls.length == 0) {
-            System.out.println("Usage: quick_start.py <atlas endpoint of format <http/https>://<atlas-fqdn>:<atlas port> like http://localhost:21000>");
-            System.exit(-1);
-        }
-
-        return urls;
-    }
-}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java b/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java
deleted file mode 100644
index 3b67706..0000000
--- a/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.atlas.examples;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.apache.atlas.ApplicationProperties;
-import org.apache.atlas.AtlasBaseClient;
-import org.apache.atlas.AtlasClientV2;
-import org.apache.atlas.AtlasException;
-import org.apache.atlas.model.typedef.AtlasTypesDef;
-import org.apache.atlas.type.AtlasType;
-import org.apache.atlas.utils.AuthenticationUtil;
-import org.apache.commons.configuration.Configuration;
-
-import java.io.Console;
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-
-/**
- * A driver that sets up types supplied in a file.  
- */
-public class UpdateTypesFromJsonFileUtil extends AtlasBaseClient{
-    public static final String ATLAS_REST_ADDRESS = "atlas.rest.address";
-
-    public static void main(String[] args) throws Exception {
-
-        Console console = System.console();
-        if (console == null) {
-            System.err.println("No console.");
-            System.exit(1);
-        }
-        String[] basicAuthUsernamePassword = null;
-        if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
-            basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput();
-        }
-        AtlasClientV2 atlasClientV2 = getAtlasClientV2(args, basicAuthUsernamePassword);
-
-
-        String createFileName = console.readLine("Enter fileName containing TypeDefs for create:- ");
-        File createFile = new File(createFileName);
-        String createJsonStr = new String( Files.readAllBytes(createFile.toPath()), StandardCharsets.UTF_8);
-
-        System.err.println("create json is :\n" + createJsonStr);
-
-        runTypeCreation(createJsonStr,atlasClientV2);
-//        String updateFileName = console.readLine("Enter fileName containing TypeDefs for update:- ");
-//        File updateFile = new File(updateFileName);
-//        String updateJsonStr = new String( Files.readAllBytes(updateFile.toPath()), StandardCharsets.UTF_8);
-//        System.err.println("update json is :\n" + updateJsonStr);
-//        runTypeUpdate(updateJsonStr,atlasClientV2);
-    }
-
-    @VisibleForTesting
-    static void runTypeCreation(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception {
-        AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
-        atlasClientV2.createAtlasTypeDefs(typesDef);
-    }
-    @VisibleForTesting
-    static void runTypeUpdate(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception {
-        AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class);
-        atlasClientV2.updateAtlasTypeDefs(typesDef);
-    }
-
-    private static AtlasClientV2 getAtlasClientV2(String[] args, String[] basicAuthUsernamePassword) throws AtlasException {
-        String[] urls = getServerUrl(args);
-
-        AtlasClientV2 atlasClientV2;
-
-        if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
-            atlasClientV2 =new AtlasClientV2(urls,basicAuthUsernamePassword);
-        } else {
-            atlasClientV2 = new AtlasClientV2(urls);
-        }
-        return atlasClientV2;
-    }
-
-    static String[] getServerUrl(String[] args) throws AtlasException {
-        if (args.length > 0) {
-            return args[0].split(",");
-        }
-
-        Configuration configuration = ApplicationProperties.get();
-        String[] urls = configuration.getStringArray(ATLAS_REST_ADDRESS);
-        if (urls == null || urls.length == 0) {
-            System.out.println("Usage: quick_start.py <atlas endpoint of format <http/https>://<atlas-fqdn>:<atlas port> like http://localhost:21000>");
-            System.exit(-1);
-        }
-
-        return urls;
-    }
-}
\ No newline at end of file