You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/01/20 01:59:57 UTC

[2/3] incubator-atlas git commit: ATLAS-1467: instance create/full-Update implementation

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityGraphDiscoveryV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityGraphDiscoveryV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityGraphDiscoveryV1.java
new file mode 100644
index 0000000..b874c5d
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityGraphDiscoveryV1.java
@@ -0,0 +1,244 @@
+/**
+ * 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.v1;
+
+import atlas.shaded.hbase.guava.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provider;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasStruct;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscovery;
+import org.apache.atlas.repository.store.graph.EntityResolver;
+import org.apache.atlas.type.AtlasArrayType;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasMapType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+
+import javax.inject.Inject;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
+
+    private AtlasTypeRegistry typeRegistry;
+
+    private Set<String> processedIds = new HashSet<>();
+
+    private EntityGraphDiscoveryContext discoveredEntities = new EntityGraphDiscoveryContext();
+
+    private final Collection<EntityResolver> entityResolvers = new LinkedHashSet<>();
+
+    @Inject
+    public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, final Collection<Provider<EntityResolver>> entityResolverProviders) {
+        this.typeRegistry = typeRegistry;
+
+        for (Provider<EntityResolver> entityResolverProvider : entityResolverProviders) {
+             entityResolvers.add(entityResolverProvider.get());
+        }
+    }
+
+    @VisibleForTesting
+    public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, final List<EntityResolver> entityResolvers) {
+        this.typeRegistry = typeRegistry;
+
+        for (EntityResolver entityResolver : entityResolvers) {
+            this.entityResolvers.add(entityResolver);
+        }
+    }
+
+    @Override
+    public void init() throws AtlasBaseException {
+        //Nothing to do
+    }
+
+    @Override
+    public EntityGraphDiscoveryContext discoverEntities(final List<AtlasEntity> entities) throws AtlasBaseException {
+
+        //walk the graph and discover entity references
+        discover(entities);
+
+        //resolve root and referred entities
+        resolveReferences();
+
+        return discoveredEntities;
+    }
+
+    @Override
+    public void cleanUp() throws AtlasBaseException {
+        processedIds.clear();
+        discoveredEntities.cleanUp();
+        final Collection<EntityResolver> entityResolvers = this.entityResolvers;
+        for (EntityResolver resolver : entityResolvers) {
+            resolver.cleanUp();
+        }
+    }
+
+
+    protected void resolveReferences() throws AtlasBaseException {
+        for (EntityResolver resolver : entityResolvers ) {
+            resolver.init(discoveredEntities);
+            resolver.resolveEntityReferences();
+        }
+    }
+
+
+    protected void discover(final List<AtlasEntity> entities) throws AtlasBaseException {
+        for (AtlasEntity entity : entities) {
+            AtlasType type = typeRegistry.getType(entity.getTypeName());
+
+            discoveredEntities.addRootEntity(entity);
+            walkEntityGraph(type, entity);
+        }
+    }
+
+    private void visitReference(AtlasEntityType type, Object entity, boolean isManagedEntity) throws AtlasBaseException {
+        if ( entity != null) {
+            if ( entity instanceof String ) {
+                String guid = (String) entity;
+                discoveredEntities.addUnResolvedIdReference(type, guid);
+            } else if ( entity instanceof AtlasObjectId ) {
+                final String guid = ((AtlasObjectId) entity).getGuid();
+                discoveredEntities.addUnResolvedIdReference(type, guid);
+            } else if ( entity instanceof  AtlasEntity ) {
+                AtlasEntity entityObj = ( AtlasEntity ) entity;
+                if (!processedIds.contains(entityObj.getGuid())) {
+                    processedIds.add(entityObj.getGuid());
+
+                    if ( isManagedEntity ) {
+                        discoveredEntities.addRootEntity(entityObj);
+                        visitStruct(type, entityObj);
+                    } else if ( entity instanceof AtlasObjectId) {
+                        discoveredEntities.addUnResolvedIdReference(type, ((AtlasObjectId) entity).getGuid());
+                    } else {
+                        discoveredEntities.addUnResolvedEntityReference(entityObj);
+                    }
+                }
+            }
+        }
+    }
+
+    void visitAttribute(AtlasStructType parentType, AtlasType attrType, AtlasStructDef.AtlasAttributeDef attrDef, Object val) throws AtlasBaseException {
+        if (val != null) {
+            if ( isPrimitive(attrType.getTypeCategory()) ) {
+                return;
+            }
+            if (attrType.getTypeCategory() == TypeCategory.ARRAY) {
+                AtlasArrayType arrayType = (AtlasArrayType) attrType;
+                AtlasType elemType = arrayType.getElementType();
+                visitCollectionReferences(parentType, attrType, attrDef, elemType, val);
+            } else if (attrType.getTypeCategory() == TypeCategory.MAP) {
+                AtlasType keyType = ((AtlasMapType) attrType).getKeyType();
+                AtlasType valueType = ((AtlasMapType) attrType).getValueType();
+                visitMapReferences(parentType, attrType, attrDef, keyType, valueType, val);
+            } else if (attrType.getTypeCategory() == TypeCategory.STRUCT) {
+                visitStruct(attrType, val);
+            } else if (attrType.getTypeCategory() == TypeCategory.ENTITY) {
+                if ( val instanceof AtlasObjectId || val instanceof String) {
+                    visitReference((AtlasEntityType) attrType,  val, false);
+                } else if ( val instanceof AtlasEntity ) {
+                    //TODO - Change this to foreign key checks after changes in the model
+                   if ( parentType.isMappedFromRefAttribute(attrDef.getName())) {
+                       visitReference((AtlasEntityType) attrType,  val, true);
+                   }
+                }
+            }
+        }
+    }
+
+    void visitMapReferences(AtlasStructType parentType, final AtlasType attrType, AtlasStructDef.AtlasAttributeDef attrDef, AtlasType keyType, AtlasType valueType, Object val) throws AtlasBaseException {
+        if (isPrimitive(keyType.getTypeCategory()) && isPrimitive(valueType.getTypeCategory())) {
+            return;
+        }
+
+        if (val != null) {
+            Iterator<Map.Entry> it = null;
+            if (Map.class.isAssignableFrom(val.getClass())) {
+                it = ((Map) val).entrySet().iterator();
+                ImmutableMap.Builder b = ImmutableMap.builder();
+                while (it.hasNext()) {
+                    Map.Entry e = it.next();
+                    visitAttribute(parentType, keyType, attrDef, e.getKey());
+                    visitAttribute(parentType, valueType, attrDef, e.getValue());
+                }
+            }
+        }
+    }
+
+    void visitCollectionReferences(final AtlasStructType parentType, final AtlasType attrType, final AtlasStructDef.AtlasAttributeDef attrDef, AtlasType elemType, Object val) throws AtlasBaseException {
+
+        if (isPrimitive(elemType.getTypeCategory())) {
+            return;
+        }
+
+        if (val != null) {
+            Iterator it = null;
+            if (val instanceof Collection) {
+                it = ((Collection) val).iterator();
+            } else if (val instanceof Iterable) {
+                it = ((Iterable) val).iterator();
+            } else if (val instanceof Iterator) {
+                it = (Iterator) val;
+            }
+            if (it != null) {
+                while (it.hasNext()) {
+                    Object elem = it.next();
+                    visitAttribute(parentType, elemType, attrDef, elem);
+                }
+            }
+        }
+    }
+
+    void visitStruct(AtlasType type, Object val) throws AtlasBaseException {
+
+        if (val == null || !(val instanceof AtlasStruct)) {
+            return;
+        }
+
+        AtlasStructType structType = (AtlasStructType) type;
+
+        for (AtlasStructDef.AtlasAttributeDef attributeDef : structType.getStructDef().getAttributeDefs()) {
+            String attrName = attributeDef.getName();
+            AtlasType attrType = structType.getAttributeType(attrName);
+            Object attrVal = ((AtlasStruct) val).getAttribute(attrName);
+            visitAttribute(structType, attrType, attributeDef, attrVal);
+        }
+    }
+
+
+    void walkEntityGraph(AtlasType type, AtlasEntity entity) throws AtlasBaseException {
+        visitStruct(type, entity);
+    }
+
+
+    boolean isPrimitive(TypeCategory typeCategory) {
+        return typeCategory == TypeCategory.PRIMITIVE || typeCategory == TypeCategory.ENUM;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
index e731c11..18e397b 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
@@ -18,25 +18,93 @@
 package org.apache.atlas.repository.store.graph.v1;
 
 
+import atlas.shaded.hbase.guava.common.annotations.VisibleForTesting;
+import com.google.inject.Inject;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.GraphTransaction;
+import org.apache.atlas.RequestContextV1;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.SearchFilter;
+import org.apache.atlas.model.TypeCategory;
 import org.apache.atlas.model.instance.AtlasClassification;
 import org.apache.atlas.model.instance.AtlasEntity;
 import org.apache.atlas.model.instance.AtlasEntityWithAssociations;
+import org.apache.atlas.model.instance.AtlasObjectId;
 import org.apache.atlas.model.instance.EntityMutationResponse;
 import org.apache.atlas.model.instance.EntityMutations;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.AtlasEntityStore;
-
+import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscovery;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
 import java.util.List;
 
 public class AtlasEntityStoreV1 implements AtlasEntityStore {
-    @Override
-    public void init() throws AtlasBaseException {
+
+    protected EntityGraphDiscovery graphDiscoverer;
+    protected AtlasTypeRegistry typeRegistry;
+
+    private EntityGraphMapper graphMapper;
+
+    private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityStoreV1.class);
+
+    @Inject
+    public AtlasEntityStoreV1(EntityGraphMapper vertexMapper) {
+        this.graphMapper = vertexMapper;
+    }
+
+    @Inject
+    public void init(AtlasTypeRegistry typeRegistry, EntityGraphDiscovery graphDiscoverer) throws AtlasBaseException {
+        this.graphDiscoverer = graphDiscoverer;
+        this.typeRegistry = typeRegistry;
     }
 
     @Override
-    public EntityMutationResponse createOrUpdate(final AtlasEntity entity) {
-        return null;
+    public EntityMutationResponse createOrUpdate(final AtlasEntity entity) throws AtlasBaseException {
+        return createOrUpdate(new ArrayList<AtlasEntity>() {{ add(entity); }});
+    }
+
+    public EntityMutationContext preCreateOrUpdate(final List<AtlasEntity> atlasEntities) throws AtlasBaseException {
+
+        EntityGraphDiscoveryContext discoveredEntities = graphDiscoverer.discoverEntities(atlasEntities);
+        EntityMutationContext context = new EntityMutationContext(discoveredEntities);
+        for (AtlasEntity entity : discoveredEntities.getRootEntities()) {
+
+            AtlasVertex vertex = null;
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("<== AtlasEntityStoreV1.preCreateOrUpdate({}): {}", entity);
+            }
+
+            AtlasEntityType entityType = (AtlasEntityType) typeRegistry.getType(entity.getTypeName());
+
+            if ( discoveredEntities.isResolved(entity.getGuid()) ) {
+                vertex = discoveredEntities.getResolvedReference(entity.getGuid());
+                context.addUpdated(entity, entityType, vertex);
+
+                String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex);
+                RequestContextV1.get().recordEntityUpdate(guid);
+            } else {
+                //Create vertices which do not exist in the repository
+                vertex = graphMapper.createVertexTemplate(entity, entityType);
+                context.addCreated(entity, entityType, vertex);
+                discoveredEntities.addRepositoryResolvedReference(new AtlasObjectId(entityType.getTypeName(), entity.getGuid()), vertex);
+
+                String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex);
+                RequestContextV1.get().recordEntityCreate(guid);
+            }
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("<== AtlasEntityStoreV1.preCreateOrUpdate({}): {}", entity, vertex);
+            }
+        }
+
+        return context;
     }
 
     @Override
@@ -55,8 +123,24 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
     }
 
     @Override
+    @GraphTransaction
     public EntityMutationResponse createOrUpdate(final List<AtlasEntity> entities) throws AtlasBaseException {
-        return null;
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasEntityStoreV1.createOrUpdate({}, {})", entities);
+        }
+
+        //Validate
+        List<AtlasEntity> normalizedEntities = validateAndNormalize(entities);
+
+        //Discover entities, create vertices
+        EntityMutationContext ctx = preCreateOrUpdate(normalizedEntities);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasStructDefStoreV1.createOrUpdate({}, {}): {}", entities);
+        }
+
+        return graphMapper.mapAttributes(ctx);
     }
 
     @Override
@@ -117,7 +201,48 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
 
     @Override
     public AtlasEntity.AtlasEntities searchEntities(final SearchFilter searchFilter) throws AtlasBaseException {
-        // TODO: Add checks here to ensure that typename and supertype are mandatory in the requests
+        // TODO: Add checks here to ensure that typename and supertype are mandatory in the request
         return null;
     }
+
+    private List<AtlasEntity> validateAndNormalize(final List<AtlasEntity> entities) throws AtlasBaseException {
+
+        List<AtlasEntity> normalizedEntities = new ArrayList<>();
+        List<String> messages = new ArrayList<>();
+
+        for (AtlasEntity entity : entities) {
+            AtlasType type = typeRegistry.getType(entity.getTypeName());
+            if (type.getTypeCategory() != TypeCategory.ENTITY) {
+                throw new AtlasBaseException(AtlasErrorCode.TYPE_MATCH_FAILED, type.getTypeCategory().name(), TypeCategory.ENTITY.name());
+            }
+
+            type.validateValue(entity, entity.getTypeName(), messages);
+
+            if ( !messages.isEmpty()) {
+                throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages);
+            }
+            AtlasEntity normalizedEntity = (AtlasEntity) type.getNormalizedValue(entity);
+            if ( normalizedEntity == null) {
+                //TODO - Fix this. Should not come here. Should ideally fail above
+                throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Failed to validate entity");
+            }
+            normalizedEntities.add(normalizedEntity);
+        }
+
+        return normalizedEntities;
+    }
+
+    @VisibleForTesting
+    EntityGraphDiscovery getGraphDiscoverer() {
+        return graphDiscoverer;
+    }
+
+    @VisibleForTesting
+    void setGraphDiscoverer(EntityGraphDiscovery discoverer) {
+        this.graphDiscoverer = discoverer;
+    }
+
+    public void cleanUp() throws AtlasBaseException {
+        this.graphDiscoverer.cleanUp();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEnumDefStoreV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEnumDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEnumDefStoreV1.java
index fccbeba..3cb10ff 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEnumDefStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEnumDefStoreV1.java
@@ -283,19 +283,19 @@ public class AtlasEnumDefStoreV1 extends AtlasAbstractDefStoreV1 implements Atla
         List<String> values = new ArrayList<>(enumDef.getElementDefs().size());
 
         for (AtlasEnumElementDef element : enumDef.getElementDefs()) {
-            String elemKey = AtlasGraphUtilsV1.getPropertyKey(enumDef, element.getValue());
+            String elemKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(enumDef, element.getValue());
 
             AtlasGraphUtilsV1.setProperty(vertex, elemKey, element.getOrdinal());
 
             if (StringUtils.isNoneBlank(element.getDescription())) {
-                String descKey = AtlasGraphUtilsV1.getPropertyKey(elemKey, "description");
+                String descKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(elemKey, "description");
 
                 AtlasGraphUtilsV1.setProperty(vertex, descKey, element.getDescription());
             }
 
             values.add(element.getValue());
         }
-        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getPropertyKey(enumDef), values);
+        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getTypeDefPropertyKey(enumDef), values);
     }
 
     private AtlasEnumDef toEnumDef(AtlasVertex vertex) {
@@ -314,10 +314,10 @@ public class AtlasEnumDefStoreV1 extends AtlasAbstractDefStoreV1 implements Atla
         typeDefStore.vertexToTypeDef(vertex, ret);
 
         List<AtlasEnumElementDef> elements = new ArrayList<>();
-        List<String> elemValues = vertex.getProperty(AtlasGraphUtilsV1.getPropertyKey(ret), List.class);
+        List<String> elemValues = vertex.getProperty(AtlasGraphUtilsV1.getTypeDefPropertyKey(ret), List.class);
         for (String elemValue : elemValues) {
-            String elemKey = AtlasGraphUtilsV1.getPropertyKey(ret, elemValue);
-            String descKey = AtlasGraphUtilsV1.getPropertyKey(elemKey, "description");
+            String elemKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(ret, elemValue);
+            String descKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(elemKey, "description");
 
             Integer ordinal = AtlasGraphUtilsV1.getProperty(vertex, elemKey, Integer.class);
             String  desc    = AtlasGraphUtilsV1.getProperty(vertex, descKey, String.class);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/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 18b3b85..1947855 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
@@ -20,16 +20,30 @@ package org.apache.atlas.repository.store.graph.v1;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasStruct;
 import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
 import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graph.GraphHelper;
 import org.apache.atlas.repository.graphdb.AtlasEdge;
 import org.apache.atlas.repository.graphdb.AtlasElement;
 import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.typesystem.persistence.Id;
+import org.apache.atlas.typesystem.types.DataTypes;
+import org.apache.atlas.typesystem.types.IDataType;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 
 /**
@@ -52,19 +66,19 @@ public class AtlasGraphUtilsV1 {
             }});
 
 
-    public static String getPropertyKey(AtlasBaseTypeDef typeDef) {
-        return getPropertyKey(typeDef.getName());
+    public static String getTypeDefPropertyKey(AtlasBaseTypeDef typeDef) {
+        return getTypeDefPropertyKey(typeDef.getName());
     }
 
-    public static String getPropertyKey(AtlasBaseTypeDef typeDef, String child) {
-        return getPropertyKey(typeDef.getName(), child);
+    public static String getTypeDefPropertyKey(AtlasBaseTypeDef typeDef, String child) {
+        return getTypeDefPropertyKey(typeDef.getName(), child);
     }
 
-    public static String getPropertyKey(String typeName) {
+    public static String getTypeDefPropertyKey(String typeName) {
         return PROPERTY_PREFIX + typeName;
     }
 
-    public static String getPropertyKey(String typeName, String child) {
+    public static String getTypeDefPropertyKey(String typeName, String child) {
         return PROPERTY_PREFIX + typeName + "." + child;
     }
 
@@ -80,6 +94,31 @@ public class AtlasGraphUtilsV1 {
         return PROPERTY_PREFIX + "edge." + fromNode + "." + toNode;
     }
 
+    public static String getAttributeEdgeLabel(AtlasStructType fromType, String attributeName) throws AtlasBaseException {
+        return GraphHelper.EDGE_LABEL_PREFIX + getQualifiedAttributePropertyKey(fromType, attributeName);
+    }
+
+    public static String getQualifiedAttributePropertyKey(AtlasStructType fromType, String attributeName) throws AtlasBaseException {
+        switch (fromType.getTypeCategory()) {
+         case STRUCT:
+         case ENTITY:
+         case CLASSIFICATION:
+             return fromType.getQualifiedAttributeName(attributeName);
+        default:
+            throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_TYPE, fromType.getTypeCategory().name());
+        }
+    }
+
+    public static boolean isReference(AtlasType type) {
+        return isReference(type.getTypeCategory());
+    }
+
+    public static boolean isReference(TypeCategory typeCategory) {
+        return typeCategory == TypeCategory.STRUCT ||
+            typeCategory == TypeCategory.ENTITY ||
+            typeCategory == TypeCategory.CLASSIFICATION;
+    }
+
     public static String encodePropertyKey(String key) {
         String ret = key;
 
@@ -104,6 +143,21 @@ public class AtlasGraphUtilsV1 {
         return ret;
     }
 
+    /**
+     * Adds an additional value to a multi-property.
+     *
+     * @param propertyName
+     * @param value
+     */
+    public static AtlasVertex addProperty(AtlasVertex vertex, String propertyName, Object value) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> addProperty({}, {}, {})", toString(vertex), propertyName, value);
+        }
+        propertyName = encodePropertyKey(propertyName);
+        vertex.addProperty(propertyName, value);
+        return vertex;
+    }
+
     public static <T extends AtlasElement> void setProperty(T element, String propertyName, Object value) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> setProperty({}, {}, {})", toString(element), propertyName, value);
@@ -127,7 +181,12 @@ public class AtlasGraphUtilsV1 {
                     LOG.debug("Setting property {} in {}", propertyName, toString(element));
                 }
 
-                element.setProperty(propertyName, value);
+                if ( value instanceof Date) {
+                    Long encodedValue = ((Date) value).getTime();
+                    element.setProperty(propertyName, encodedValue);
+                } else {
+                    element.setProperty(propertyName, value);
+                }
             }
         }
     }
@@ -186,4 +245,13 @@ public class AtlasGraphUtilsV1 {
         return String.format("edge[id=%s label=%s from %s -> to %s]", edge.getId(), edge.getLabel(),
                 toString(edge.getOutVertex()), toString(edge.getInVertex()));
     }
+
+    public static AtlasEntity.Status getState(AtlasElement element) {
+        String state = getStateAsString(element);
+        return state == null ? null : AtlasEntity.Status.valueOf(state);
+    }
+
+    public static String getStateAsString(AtlasElement element) {
+        return element.getProperty(Constants.STATE_PROPERTY_KEY, String.class);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasStructDefStoreV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasStructDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasStructDefStoreV1.java
index e780dc1..425bde9 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasStructDefStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasStructDefStoreV1.java
@@ -390,13 +390,13 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
         List<String> attrNames = new ArrayList<>(structDef.getAttributeDefs().size());
 
         for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
-            String propertyKey = AtlasGraphUtilsV1.getPropertyKey(structDef, attributeDef.getName());
+            String propertyKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(structDef, attributeDef.getName());
 
             AtlasGraphUtilsV1.setProperty(vertex, propertyKey, toJsonFromAttributeDef(attributeDef, structType));
 
             attrNames.add(attributeDef.getName());
         }
-        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getPropertyKey(structDef), attrNames);
+        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getTypeDefPropertyKey(structDef), attrNames);
     }
 
     public static void updateVertexPreUpdate(AtlasStructDef structDef, AtlasStructType structType,
@@ -410,7 +410,7 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
             }
         }
 
-        List<String> currAttrNames = vertex.getProperty(AtlasGraphUtilsV1.getPropertyKey(structDef), List.class);
+        List<String> currAttrNames = vertex.getProperty(AtlasGraphUtilsV1.getTypeDefPropertyKey(structDef), List.class);
 
         // delete attributes that are not present in updated structDef
         if (CollectionUtils.isNotEmpty(currAttrNames)) {
@@ -434,13 +434,13 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
                     }
                 }
 
-                String propertyKey = AtlasGraphUtilsV1.getPropertyKey(structDef, attributeDef.getName());
+                String propertyKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(structDef, attributeDef.getName());
 
                 AtlasGraphUtilsV1.setProperty(vertex, propertyKey, toJsonFromAttributeDef(attributeDef, structType));
             }
         }
 
-        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getPropertyKey(structDef), attrNames);
+        AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getTypeDefPropertyKey(structDef), attrNames);
     }
 
     public static void updateVertexAddReferences(AtlasStructDef structDef, AtlasVertex vertex,
@@ -457,11 +457,11 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
         typeDefStore.vertexToTypeDef(vertex, ret);
 
         List<AtlasAttributeDef> attributeDefs = new ArrayList<>();
-        List<String> attrNames = vertex.getProperty(AtlasGraphUtilsV1.getPropertyKey(ret), List.class);
+        List<String> attrNames = vertex.getProperty(AtlasGraphUtilsV1.getTypeDefPropertyKey(ret), List.class);
 
         if (CollectionUtils.isNotEmpty(attrNames)) {
             for (String attrName : attrNames) {
-                String propertyKey = AtlasGraphUtilsV1.getPropertyKey(ret, attrName);
+                String propertyKey = AtlasGraphUtilsV1.getTypeDefPropertyKey(ret, attrName);
                 String attribJson  = vertex.getProperty(propertyKey, String.class);
 
                 attributeDefs.add(toAttributeDefFromJson(structDef, AtlasType.fromJson(attribJson, Map.class),
@@ -586,12 +586,12 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
 
                     String       refAttributeName = null;
                     List<String> attrNames        = attributeType.getProperty(
-                                                            AtlasGraphUtilsV1.getPropertyKey(attrTypeName), List.class);
+                                                            AtlasGraphUtilsV1.getTypeDefPropertyKey(attrTypeName), List.class);
 
                     if (CollectionUtils.isNotEmpty(attrNames)) {
                         for (String attrName : attrNames) {
                             String attribJson = attributeType.getProperty(
-                                                AtlasGraphUtilsV1.getPropertyKey(attrTypeName, attrName), String.class);
+                                                AtlasGraphUtilsV1.getTypeDefPropertyKey(attrTypeName, attrName), String.class);
 
                             Map    refAttrInfo            = AtlasType.fromJson(attribJson, Map.class);
                             String refAttribType          = (String) refAttrInfo.get("dataType");

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/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
new file mode 100644
index 0000000..3b557e6
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
@@ -0,0 +1,539 @@
+/**
+ * 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.v1;
+
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graph.AtlasEdgeLabel;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasArrayType;
+import org.apache.atlas.type.AtlasClassificationType;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasMapType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+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.string;
+
+public abstract class DeleteHandlerV1 {
+
+    public static final Logger LOG = LoggerFactory.getLogger(DeleteHandlerV1.class);
+
+    private AtlasTypeRegistry typeRegistry;
+    private boolean shouldUpdateReverseAttribute;
+    private boolean softDelete;
+
+    protected static final GraphHelper graphHelper = GraphHelper.getInstance();
+
+    public DeleteHandlerV1(AtlasTypeRegistry typeRegistry, boolean shouldUpdateReverseAttribute, boolean softDelete) {
+        this.typeRegistry = typeRegistry;
+        this.shouldUpdateReverseAttribute = shouldUpdateReverseAttribute;
+        this.softDelete = softDelete;
+    }
+
+    /**
+     * Deletes the specified entity vertices.
+     * Deletes any traits, composite entities, and structs owned by each entity.
+     * Also deletes all the references from/to the entity.
+     *
+     * @param instanceVertices
+     * @throws AtlasException
+     */
+    public void deleteEntities(List<AtlasVertex> instanceVertices) throws AtlasBaseException {
+        RequestContextV1 requestContext = RequestContextV1.get();
+
+        Set<AtlasVertex> deletionCandidateVertices = new HashSet<>();
+
+        for (AtlasVertex instanceVertex : instanceVertices) {
+            String guid = GraphHelper.getGuid(instanceVertex);
+            AtlasEntity.Status state = AtlasGraphUtilsV1.getState(instanceVertex);
+            if (requestContext.getDeletedEntityIds().contains(guid) || state == AtlasEntity.Status.DELETED) {
+                LOG.debug("Skipping deletion of {} as it is already deleted", guid);
+                continue;
+            }
+
+            // Get GUIDs and vertices for all deletion candidates.
+            Set<GraphHelper.VertexInfo> compositeVertices = getCompositeVertices(instanceVertex);
+
+            // Record all deletion candidate GUIDs in RequestContext
+            // and gather deletion candidate vertices.
+            for (GraphHelper.VertexInfo vertexInfo : compositeVertices) {
+                requestContext.recordEntityDelete(vertexInfo.getGuid());
+                deletionCandidateVertices.add(vertexInfo.getVertex());
+            }
+        }
+
+        // Delete traits and vertices.
+        for (AtlasVertex deletionCandidateVertex : deletionCandidateVertices) {
+            deleteAllTraits(deletionCandidateVertex);
+            deleteTypeVertex(deletionCandidateVertex, 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.
+     *
+     * @param entityVertex the root entity vertex
+     * @return set of VertexInfo for all composite entities
+     * @throws AtlasException
+     */
+    public Set<GraphHelper.VertexInfo> getCompositeVertices(AtlasVertex entityVertex) throws AtlasBaseException {
+        Set<GraphHelper.VertexInfo> result = new HashSet<>();
+        Stack<AtlasVertex> vertices = new Stack<>();
+        vertices.push(entityVertex);
+        while (vertices.size() > 0) {
+            AtlasVertex vertex = vertices.pop();
+            String typeName = GraphHelper.getTypeName(vertex);
+            String guid = GraphHelper.getGuid(vertex);
+            AtlasEntity.Status state = AtlasGraphUtilsV1.getState(vertex);
+            if (state == AtlasEntity.Status.DELETED) {
+                //If the reference vertex is marked for deletion, skip it
+                continue;
+            }
+            result.add(new GraphHelper.VertexInfo(guid, vertex, typeName));
+            AtlasEntityType entityType = (AtlasEntityType) typeRegistry.getType(typeName);
+            for (AtlasStructType.AtlasAttribute attributeInfo : entityType.getAllAttributes().values()) {
+                if (!entityType.isMappedFromRefAttribute(attributeInfo.getAttributeDef().getName())) {
+                    continue;
+                }
+                String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(entityType, attributeInfo.getAttributeDef().getName());
+                AtlasType attrType = typeRegistry.getType(attributeInfo.getAttributeDef().getTypeName());
+                switch (attrType.getTypeCategory()) {
+                case ENTITY:
+                    AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel);
+                    if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                        AtlasVertex compositeVertex = edge.getInVertex();
+                        vertices.push(compositeVertex);
+                    }
+                    break;
+                case ARRAY:
+                    AtlasArrayType arrType = (AtlasArrayType) attrType;
+                    if (arrType.getElementType().getTypeCategory() != TypeCategory.ENTITY) {
+                        continue;
+                    }
+                    Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(vertex, edgeLabel);
+                    if (edges != null) {
+                        while (edges.hasNext()) {
+                            edge = edges.next();
+                            if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                                AtlasVertex compositeVertex = edge.getInVertex();
+                                vertices.push(compositeVertex);
+                            }
+                        }
+                    }
+                    break;
+                case MAP:
+                    AtlasMapType mapType = (AtlasMapType) attrType;
+                    TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
+                    if (valueTypeCategory != TypeCategory.ENTITY) {
+                        continue;
+                    }
+                    String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(entityType, attributeInfo.getAttributeDef().getName());
+                    List<String> keys = vertex.getProperty(propertyName, List.class);
+                    if (keys != null) {
+                        for (String key : keys) {
+                            String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, key);
+                            edge = graphHelper.getEdgeForLabel(vertex, mapEdgeLabel);
+                            if (edge != null && AtlasGraphUtilsV1.getState(edge) == AtlasEntity.Status.ACTIVE) {
+                                AtlasVertex compositeVertex = edge.getInVertex();
+                                vertices.push(compositeVertex);
+                            }
+                        }
+                    }
+                    break;
+                default:
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Force delete is used to remove struct/trait in case of entity updates
+     * @param edge
+     * @param typeCategory
+     * @param isComposite
+     * @param forceDeleteStructTrait
+     * @return returns true if the edge reference is hard deleted
+     * @throws AtlasException
+     */
+    public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isComposite,
+        boolean forceDeleteStructTrait) throws AtlasBaseException {
+        LOG.debug("Deleting {}", string(edge));
+        boolean forceDelete =
+            (AtlasGraphUtilsV1.isReference(typeCategory))
+                ? forceDeleteStructTrait : false;
+        if (AtlasGraphUtilsV1.isReference(typeCategory) && isComposite) {
+            //If the vertex is of type struct/trait, delete the edge and then the reference vertex as the vertex is not shared by any other entities.
+            //If the vertex is of type class, and its composite attribute, this reference vertex' lifecycle is controlled
+            //through this delete, hence delete the edge and the reference vertex.
+            AtlasVertex vertexForDelete = edge.getInVertex();
+
+            //If deleting the edge and then the in vertex, reverse attribute shouldn't be updated
+            deleteEdge(edge, false, forceDelete);
+            deleteTypeVertex(vertexForDelete, typeCategory, forceDelete);
+        } else {
+            //If the vertex is of type class, and its not a composite attributes, the reference AtlasVertex' lifecycle is not controlled
+            //through this delete. Hence just remove the reference edge. Leave the reference AtlasVertex as is
+
+            //If deleting just the edge, reverse attribute should be updated for any references
+            //For example, for the department type system, if the person's manager edge is deleted, subordinates of manager should be updated
+            deleteEdge(edge, true, false);
+        }
+        return !softDelete || forceDelete;
+    }
+
+    protected void deleteEdge(AtlasEdge edge, boolean updateReverseAttribute, boolean force) throws AtlasBaseException {
+        //update reverse attribute
+        if (updateReverseAttribute) {
+            AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(edge.getLabel());
+
+            AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
+
+            if (parentType instanceof AtlasStructType) {
+                AtlasStructType parentStructType = (AtlasStructType) parentType;
+                if (parentStructType.isForeignKeyAttribute(atlasEdgeLabel.getAttributeName())) {
+                    deleteEdgeBetweenVertices(edge.getInVertex(), edge.getOutVertex(), atlasEdgeLabel.getAttributeName());
+                }
+            }
+        }
+
+        deleteEdge(edge, force);
+
+    }
+
+
+    protected void deleteTypeVertex(AtlasVertex instanceVertex, TypeCategory typeCategory, boolean force) throws AtlasBaseException {
+        switch (typeCategory) {
+        case STRUCT:
+        case CLASSIFICATION:
+            deleteTypeVertex(instanceVertex, force);
+            break;
+
+        case ENTITY:
+            deleteEntities(Collections.singletonList(instanceVertex));
+            break;
+
+        default:
+            throw new IllegalStateException("Type category " + typeCategory + " not handled");
+        }
+    }
+
+    /**
+     * Deleting any type vertex. Goes over the complex attributes and removes the references
+     * @param instanceVertex
+     * @throws AtlasException
+     */
+    protected void deleteTypeVertex(AtlasVertex instanceVertex, boolean force) throws AtlasBaseException {
+        LOG.debug("Deleting {}", string(instanceVertex));
+        String typeName = GraphHelper.getTypeName(instanceVertex);
+
+
+        AtlasType parentType = typeRegistry.getType(typeName);
+
+        if (parentType instanceof AtlasStructType) {
+
+            AtlasStructType entityType = (AtlasStructType) parentType;
+            for (AtlasStructType.AtlasAttribute attributeInfo : getAttributes(entityType)) {
+                LOG.debug("Deleting attribute {} for {}", attributeInfo.getAttributeDef().getName(), string(instanceVertex));
+
+                AtlasType attrType = typeRegistry.getType(attributeInfo.getAttributeType().getTypeName());
+
+                String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(entityType, attributeInfo.getAttributeDef().getName());
+
+                switch (attrType.getTypeCategory()) {
+                case ENTITY:
+                    //If its class attribute, delete the reference
+                    deleteEdgeReference(instanceVertex, edgeLabel, TypeCategory.ENTITY, entityType.isMappedFromRefAttribute(attributeInfo.getAttributeDef().getName()));
+                    break;
+
+                case STRUCT:
+                    //If its struct attribute, delete the reference
+                    deleteEdgeReference(instanceVertex, edgeLabel, TypeCategory.STRUCT, false);
+                    break;
+
+                case ARRAY:
+                    //For array attribute, if the element is struct/class, delete all the references
+                    AtlasArrayType arrType = (AtlasArrayType) attrType;
+                    AtlasType elemType = arrType.getElementType();
+                    if (AtlasGraphUtilsV1.isReference(elemType.getTypeCategory())) {
+                        Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(instanceVertex, edgeLabel);
+                        if (edges != null) {
+                            while (edges.hasNext()) {
+                                AtlasEdge edge = edges.next();
+                                deleteEdgeReference(edge, elemType.getTypeCategory(), entityType.isMappedFromRefAttribute(attributeInfo.getAttributeDef().getName()), false);
+                            }
+                        }
+                    }
+                    break;
+
+                case MAP:
+                    //For map attribute, if the value type is struct/class, delete all the references
+                    AtlasMapType mapType = (AtlasMapType) attrType;
+                    AtlasType keyType = mapType.getKeyType();
+                    TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
+                    String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(entityType, attributeInfo.getAttributeDef().getName());
+
+                    if (AtlasGraphUtilsV1.isReference(valueTypeCategory)) {
+                        List<Object> keys = ArrayVertexMapper.getArrayElementsProperty(keyType, instanceVertex, propertyName);
+                        if (keys != null) {
+                            for (Object key : keys) {
+                                String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, (String) key);
+                                deleteEdgeReference(instanceVertex, mapEdgeLabel, valueTypeCategory, entityType.isMappedFromRefAttribute(attributeInfo.getAttributeDef().getName()));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        deleteVertex(instanceVertex, force);
+    }
+
+    public void deleteEdgeReference(AtlasVertex outVertex, String edgeLabel, TypeCategory typeCategory,
+        boolean isComposite) throws AtlasBaseException {
+        AtlasEdge edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
+        if (edge != null) {
+            deleteEdgeReference(edge, typeCategory, isComposite, false);
+        }
+    }
+
+    /**
+     * Delete all traits from the specified vertex.
+     * @param instanceVertex
+     * @throws AtlasException
+     */
+    private void deleteAllTraits(AtlasVertex instanceVertex) throws AtlasBaseException {
+        List<String> traitNames = GraphHelper.getTraitNames(instanceVertex);
+        LOG.debug("Deleting traits {} for {}", traitNames, string(instanceVertex));
+        String typeName = GraphHelper.getTypeName(instanceVertex);
+
+        for (String traitNameToBeDeleted : traitNames) {
+            String relationshipLabel = GraphHelper.getTraitLabel(typeName, traitNameToBeDeleted);
+            deleteEdgeReference(instanceVertex, relationshipLabel, TypeCategory.CLASSIFICATION, false);
+        }
+    }
+
+    protected AtlasStructDef.AtlasAttributeDef getAttributeForEdge(String edgeLabel) throws AtlasBaseException {
+        AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(edgeLabel);
+
+        AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
+        AtlasStructType parentStructType = (AtlasStructType) parentType;
+
+        return parentStructType.getAttributeDef(atlasEdgeLabel.getAttributeName());
+    }
+
+    protected abstract void _deleteVertex(AtlasVertex instanceVertex, boolean force);
+
+    protected abstract void deleteEdge(AtlasEdge edge, boolean force) throws AtlasBaseException;
+
+    /**
+     * Deletes the edge between outvertex and inVertex. The edge is for attribute attributeName of outVertex
+     * @param outVertex
+     * @param inVertex
+     * @param attributeName
+     * @throws AtlasException
+     */
+    protected void deleteEdgeBetweenVertices(AtlasVertex outVertex, AtlasVertex inVertex, String attributeName) throws AtlasBaseException {
+        LOG.debug("Removing edge from {} to {} with attribute name {}", string(outVertex), string(inVertex),
+            attributeName);
+        String typeName = GraphHelper.getTypeName(outVertex);
+        String outId = GraphHelper.getGuid(outVertex);
+        AtlasEntity.Status state = AtlasGraphUtilsV1.getState(outVertex);
+        if ((outId != null && RequestContextV1.get().isDeletedEntity(outId)) || state == AtlasEntity.Status.DELETED) {
+            //If the reference vertex is marked for deletion, skip updating the reference
+            return;
+        }
+
+        AtlasStructType parentType = (AtlasStructType) typeRegistry.getType(typeName);
+        String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(parentType, attributeName);
+        String edgeLabel = EDGE_LABEL_PREFIX + propertyName;
+        AtlasEdge edge = null;
+
+        AtlasStructDef.AtlasAttributeDef attrDef = parentType.getAttributeDef(attributeName);
+        AtlasType attrType = typeRegistry.getType(attrDef.getTypeName());
+
+        switch (attrType.getTypeCategory()) {
+        case ENTITY:
+            //If its class attribute, its the only edge between two vertices
+            if (attrDef.getIsOptional()) {
+                edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
+                if (shouldUpdateReverseAttribute) {
+                    GraphHelper.setProperty(outVertex, propertyName, null);
+                }
+            } else {
+                // Cannot unset a required attribute.
+                throw new AtlasBaseException("Cannot unset required attribute " + propertyName +
+                    " on " + GraphHelper.getVertexDetails(outVertex) + " edge = " + edgeLabel);
+            }
+            break;
+
+        case ARRAY:
+            //If its array attribute, find the right edge between the two vertices and update array property
+            List<String> elements = GraphHelper.getListProperty(outVertex, propertyName);
+            if (elements != null) {
+                elements = new ArrayList<>(elements);   //Make a copy, else list.remove reflects on titan.getProperty()
+                for (String elementEdgeId : elements) {
+                    AtlasEdge elementEdge = graphHelper.getEdgeByEdgeId(outVertex, edgeLabel, elementEdgeId);
+                    if (elementEdge == null) {
+                        continue;
+                    }
+
+                    AtlasVertex elementVertex = elementEdge.getInVertex();
+                    if (elementVertex.equals(inVertex)) {
+                        edge = elementEdge;
+
+                        //TODO element.size includes deleted items as well. should exclude
+                        if (!attrDef.getIsOptional()
+                            && elements.size() <= attrDef.getValuesMinCount()) {
+                            // Deleting this edge would violate the attribute's lower bound.
+                            throw new AtlasBaseException(
+                                "Cannot remove array element from required attribute " +
+                                    propertyName + " on "
+                                    + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(elementEdge));
+                        }
+
+                        if (shouldUpdateReverseAttribute) {
+                            //if composite attribute, remove the reference as well. else, just remove the edge
+                            //for example, when table is deleted, process still references the table
+                            //but when column is deleted, table will not reference the deleted column
+                            LOG.debug("Removing edge {} from the array attribute {}", string(elementEdge),
+                                attributeName);
+                            elements.remove(elementEdge.getId().toString());
+                            GraphHelper.setProperty(outVertex, propertyName, elements);
+                            break;
+
+                        }
+                    }
+                }
+            }
+            break;
+
+        case MAP:
+            //If its map attribute, find the right edge between two vertices and update map property
+            List<String> keys = GraphHelper.getListProperty(outVertex, propertyName);
+            if (keys != null) {
+                keys = new ArrayList<>(keys);   //Make a copy, else list.remove reflects on titan.getProperty()
+                for (String key : keys) {
+                    String keyPropertyName = GraphHelper.getQualifiedNameForMapKey(propertyName, key);
+                    String mapEdgeId = GraphHelper.getSingleValuedProperty(outVertex, keyPropertyName, String.class);
+                    AtlasEdge mapEdge = graphHelper.getEdgeByEdgeId(outVertex, keyPropertyName, mapEdgeId);
+                    if(mapEdge != null) {
+                        AtlasVertex mapVertex = mapEdge.getInVertex();
+                        if (mapVertex.getId().toString().equals(inVertex.getId().toString())) {
+                            //TODO keys.size includes deleted items as well. should exclude
+                            if (attrDef.getIsOptional() || keys.size() > attrDef.getValuesMinCount()) {
+                                edge = mapEdge;
+                            } else {
+                                // Deleting this entry would violate the attribute's lower bound.
+                                throw new AtlasBaseException(
+                                    "Cannot remove map entry " + keyPropertyName + " from required attribute " +
+                                        propertyName + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(mapEdge));
+                            }
+
+                            if (shouldUpdateReverseAttribute) {
+                                //remove this key
+                                LOG.debug("Removing edge {}, key {} from the map attribute {}", string(mapEdge), key,
+                                    attributeName);
+                                keys.remove(key);
+                                GraphHelper.setProperty(outVertex, propertyName, keys);
+                                GraphHelper.setProperty(outVertex, keyPropertyName, null);
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+            break;
+
+        case STRUCT:
+        case CLASSIFICATION:
+            break;
+
+        default:
+            throw new IllegalStateException("There can't be an edge from " + GraphHelper.getVertexDetails(outVertex) + " to "
+                + GraphHelper.getVertexDetails(inVertex) + " with attribute name " + attributeName + " which is not class/array/map attribute");
+        }
+
+        if (edge != null) {
+            deleteEdge(edge, false);
+            RequestContextV1 requestContext = RequestContextV1.get();
+            GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
+                requestContext.getRequestTime());
+            GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
+            requestContext.recordEntityUpdate(outId);
+        }
+    }
+
+    protected void deleteVertex(AtlasVertex instanceVertex, boolean force) throws AtlasBaseException {
+        //Update external references(incoming edges) to this vertex
+        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);
+            if (edgeState == AtlasEntity.Status.ACTIVE) {
+                //Delete only the active edge references
+                AtlasStructDef.AtlasAttributeDef attribute = getAttributeForEdge(edge.getLabel());
+                //TODO use delete edge instead??
+                deleteEdgeBetweenVertices(edge.getOutVertex(), edge.getInVertex(), attribute.getName());
+            }
+        }
+        _deleteVertex(instanceVertex, force);
+    }
+
+    private Collection<AtlasStructType.AtlasAttribute> getAttributes(AtlasStructType structType) {
+        Collection<AtlasStructType.AtlasAttribute> ret = null;
+
+        if (structType.getTypeCategory() == TypeCategory.STRUCT) {
+            ret = structType.getAllAttributes().values();
+        } else if (structType.getTypeCategory() == TypeCategory.CLASSIFICATION) {
+            ret = ((AtlasClassificationType)structType).getAllAttributes().values();
+        } else if (structType.getTypeCategory() == TypeCategory.ENTITY) {
+            ret = ((AtlasEntityType)structType).getAllAttributes().values();
+        } else {
+            ret = Collections.emptyList();
+        }
+
+        return ret;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/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
new file mode 100644
index 0000000..174e490
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
@@ -0,0 +1,185 @@
+/**
+ * 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.v1;
+
+
+import com.google.inject.Inject;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasStruct;
+import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.model.instance.EntityMutations;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.RepositoryException;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasStructType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
+
+public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EntityGraphMapper.class);
+
+    protected final GraphHelper graphHelper = GraphHelper.getInstance();
+
+    protected EntityMutationContext context;
+
+    protected final StructVertexMapper structVertexMapper;
+
+    @Inject
+    public EntityGraphMapper(ArrayVertexMapper arrayVertexMapper, MapVertexMapper mapVertexMapper) {
+        this.structVertexMapper = new StructVertexMapper(arrayVertexMapper, mapVertexMapper);
+        arrayVertexMapper.init(structVertexMapper);
+        mapVertexMapper.init(structVertexMapper);
+    }
+
+    public AtlasVertex createVertexTemplate(final AtlasStruct instance, final AtlasStructType structType) {
+        AtlasVertex vertex = structVertexMapper.createVertexTemplate(instance, structType);
+        
+        AtlasEntityType entityType = (AtlasEntityType) structType;
+        AtlasEntity entity = (AtlasEntity) instance;
+
+        // add super types
+        for (String superTypeName : entityType.getAllSuperTypes()) {
+            AtlasGraphUtilsV1.addProperty(vertex, Constants.SUPER_TYPES_PROPERTY_KEY, superTypeName);
+        }
+
+        final String guid = UUID.randomUUID().toString();
+
+        // add identity
+        AtlasGraphUtilsV1.setProperty(vertex, Constants.GUID_PROPERTY_KEY, guid);
+
+        // add version information
+        AtlasGraphUtilsV1.setProperty(vertex, Constants.VERSION_PROPERTY_KEY, Integer.valueOf(entity.getVersion().intValue()));
+
+        return vertex;
+    }
+
+
+    @Override
+    public AtlasEdge toGraph(GraphMutationContext ctx) throws AtlasBaseException {
+        AtlasEdge result = null;
+
+        String guid = getId(ctx.getValue());
+
+        AtlasVertex entityVertex = context.getDiscoveryContext().getResolvedReference(guid);
+        String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(ctx.getParentType(), ctx.getAttributeDef().getName());
+        if ( ctx.getCurrentEdge().isPresent() ) {
+            updateEdge(ctx.getAttributeDef(), ctx.getValue(), ctx.getCurrentEdge().get(), entityVertex);
+            result = ctx.getCurrentEdge().get();
+        } else {
+            try {
+                result = graphHelper.getOrCreateEdge(ctx.getReferringVertex(), entityVertex, edgeLabel);
+            } catch (RepositoryException e) {
+                throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, e);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public void cleanUp() throws AtlasBaseException {
+    }
+
+    private AtlasEdge updateEdge(AtlasStructDef.AtlasAttributeDef attributeDef, Object value,  AtlasEdge currentEdge, final AtlasVertex entityVertex) throws AtlasBaseException {
+
+        LOG.debug("Updating entity reference {} for reference attribute {}",  attributeDef.getName());
+        // Update edge if it exists
+
+        AtlasVertex currentVertex = currentEdge.getOutVertex();
+        String currentEntityId = AtlasGraphUtilsV1.getIdFromVertex(currentVertex);
+        String newEntityId = getId(value);
+        AtlasEdge newEdge = currentEdge;
+        if (!currentEntityId.equals(newEntityId)) {
+            // add an edge to the class vertex from the instance
+            if (entityVertex != null) {
+                try {
+                    newEdge = graphHelper.getOrCreateEdge(currentEdge.getInVertex(), entityVertex, currentEdge.getLabel());
+                } catch (RepositoryException e) {
+                    throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, e);
+                }
+
+            }
+        }
+        return newEdge;
+    }
+
+    public EntityMutationResponse mapAttributes(EntityMutationContext ctx) throws AtlasBaseException {
+
+        this.context = ctx;
+        structVertexMapper.init(this);
+
+        EntityMutationResponse resp = new EntityMutationResponse();
+        //Map attributes
+        if (ctx.getCreatedEntities() != null) {
+            for (AtlasEntity createdEntity : ctx.getCreatedEntities()) {
+                AtlasVertex vertex = ctx.getVertex(createdEntity);
+                structVertexMapper.mapAttributestoVertex((AtlasStructType) ctx.getType(createdEntity), createdEntity, vertex);
+                resp.addEntity(EntityMutations.EntityOperation.CREATE, constructHeader(createdEntity, vertex));
+            }
+        }
+
+        if (ctx.getUpdatedEntities() != null) {
+            for (AtlasEntity updated : ctx.getUpdatedEntities()) {
+                AtlasVertex vertex = ctx.getVertex(updated);
+                structVertexMapper.mapAttributestoVertex((AtlasStructType) ctx.getType(updated), updated, vertex);
+
+                resp.addEntity(EntityMutations.EntityOperation.UPDATE, constructHeader(updated, vertex));
+            }
+        }
+
+        return resp;
+    }
+
+
+    public String getId(Object value) throws AtlasBaseException {
+        if ( value != null) {
+            if ( value instanceof  AtlasObjectId) {
+                return ((AtlasObjectId) value).getGuid();
+            } else if (value instanceof AtlasEntity) {
+                return ((AtlasEntity) value).getGuid();
+            }
+        }
+        throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, (String) value);
+    }
+
+    private AtlasEntityHeader constructHeader(AtlasEntity entity, AtlasVertex vertex) {
+        //TODO - enhance to return only selective attributes
+        return new AtlasEntityHeader(entity.getTypeName(), AtlasGraphUtilsV1.getIdFromVertex(vertex), entity.getAttributes());
+    }
+
+    public EntityMutationContext getContext() {
+        return context;
+    }
+
+    public AtlasEntityType getInstanceType(Object val) throws AtlasBaseException {
+        String guid = getId(val);
+        return (AtlasEntityType) getContext().getType(guid);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityMutationContext.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityMutationContext.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityMutationContext.java
new file mode 100644
index 0000000..f942a91
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityMutationContext.java
@@ -0,0 +1,124 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph.v1;
+
+import org.apache.atlas.model.instance.AtlasEntity;
+
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
+import org.apache.atlas.type.AtlasType;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class EntityMutationContext {
+
+    private List<AtlasEntity> entitiesCreated  = new ArrayList<>();
+    private List<AtlasEntity> entitiesUpdated  = new ArrayList<>();
+
+    private EntityGraphDiscoveryContext context;
+    private Map<String, AtlasType> entityVsType = new HashMap<>();
+    private Map<String, AtlasVertex> entityVsVertex = new HashMap<>();
+
+    public EntityMutationContext(final EntityGraphDiscoveryContext context) {
+        this.context = context;
+    }
+
+    public void addCreated(AtlasEntity entity, AtlasType type, AtlasVertex atlasVertex) {
+        entitiesCreated.add(entity);
+        entityVsVertex.put(entity.getGuid(), atlasVertex);
+        entityVsType.put(entity.getGuid(), type);
+    }
+
+    public void addUpdated(AtlasEntity entity, AtlasType type, AtlasVertex atlasVertex) {
+        entitiesUpdated.add(entity);
+        entityVsVertex.put(entity.getGuid(), atlasVertex);
+        entityVsType.put(entity.getGuid(), type);
+    }
+
+    public Collection<AtlasEntity> getCreatedEntities() {
+        return entitiesCreated;
+    }
+
+    public Collection<AtlasEntity> getUpdatedEntities() {
+        return entitiesUpdated;
+    }
+
+    public AtlasType getType(AtlasEntity entity) {
+        return entityVsType.get(entity.getGuid());
+    }
+
+    public AtlasType getType(String entityId) {
+        return entityVsType.get(entityId);
+    }
+
+    public AtlasVertex getVertex(AtlasEntity entity) {
+        return entityVsVertex.get(entity.getGuid());
+    }
+
+    public AtlasVertex getVertex(String entityId) {
+        return entityVsVertex.get(entityId);
+    }
+
+    public EntityGraphDiscoveryContext getDiscoveryContext() {
+        return this.context;
+    }
+
+    //TODO - equals/hashCode/toString
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        final EntityMutationContext that = (EntityMutationContext) o;
+
+        if (entitiesCreated != null ? !entitiesCreated.equals(that.entitiesCreated) : that.entitiesCreated != null)
+            return false;
+        if (entitiesUpdated != null ? !entitiesUpdated.equals(that.entitiesUpdated) : that.entitiesUpdated != null)
+            return false;
+        if (context != null ? !context.equals(that.context) : that.context != null) return false;
+        if (entityVsType != null ? !entityVsType.equals(that.entityVsType) : that.entityVsType != null) return false;
+        return !(entityVsVertex != null ? !entityVsVertex.equals(that.entityVsVertex) : that.entityVsVertex != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = entitiesCreated != null ? entitiesCreated.hashCode() : 0;
+        result = 31 * result + (entitiesUpdated != null ? entitiesUpdated.hashCode() : 0);
+        result = 31 * result + (context != null ? context.hashCode() : 0);
+        result = 31 * result + (entityVsType != null ? entityVsType.hashCode() : 0);
+        result = 31 * result + (entityVsVertex != null ? entityVsVertex.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "EntityMutationContext{" +
+            "entitiesCreated=" + entitiesCreated +
+            ", entitiesUpdated=" + entitiesUpdated +
+            ", context=" + context +
+            ", entityVsType=" + entityVsType +
+            ", entityVsVertex=" + entityVsVertex +
+            '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/GraphMutationContext.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/GraphMutationContext.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/GraphMutationContext.java
new file mode 100644
index 0000000..d5ba7e1
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/GraphMutationContext.java
@@ -0,0 +1,195 @@
+/**
+ * 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.v1;
+
+
+import com.google.common.base.Optional;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+
+import java.util.Objects;
+
+public class GraphMutationContext {
+
+
+    /**
+     * Atlas Attribute
+     */
+
+    private AtlasStructType.AtlasAttribute attribute;
+
+    /**
+     * Overriding type for which elements are being mapped
+     */
+    private AtlasType currentElementType;
+
+    /**
+     * Current attribute value/entity/Struct instance
+     */
+    private Object value;
+
+    /**
+     *
+     * The vertex which corresponds to the entity/struct for which we are mapping a complex attributes like struct, traits
+     */
+    AtlasVertex referringVertex;
+
+    /**
+     * the vertex property that we are updating
+     */
+
+    String vertexPropertyKey;
+
+    /**
+     * The current edge(in case of updates) from the parent entity/struct to the complex attribute like struct, trait
+     */
+    Optional<AtlasEdge> existingEdge;
+
+
+    private GraphMutationContext(final Builder builder) {
+        this.attribute = builder.attribute;
+        this.currentElementType = builder.elementType;
+        this.existingEdge = builder.currentEdge;
+        this.value = builder.currentValue;
+        this.referringVertex = builder.referringVertex;
+        this.vertexPropertyKey = builder.vertexPropertyKey;
+    }
+
+    public String getVertexPropertyKey() {
+        return vertexPropertyKey;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(attribute, value, referringVertex, vertexPropertyKey, existingEdge);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else if (obj.getClass() != getClass()) {
+            return false;
+        } else {
+            GraphMutationContext rhs = (GraphMutationContext) obj;
+            return Objects.equals(attribute, rhs.getAttribute())
+                 && Objects.equals(value, rhs.getValue())
+                 && Objects.equals(referringVertex, rhs.getReferringVertex())
+                 && Objects.equals(vertexPropertyKey, rhs.getReferringVertex())
+                 && Objects.equals(existingEdge, rhs.getCurrentEdge());
+        }
+    }
+
+
+    public static final class Builder {
+
+        private final AtlasStructType.AtlasAttribute attribute;
+
+        private final AtlasType elementType;
+
+        private final Object currentValue;
+
+        private AtlasVertex referringVertex;
+
+        private Optional<AtlasEdge> currentEdge = Optional.absent();
+
+        private  String vertexPropertyKey;
+
+
+        public Builder(AtlasStructType.AtlasAttribute attribute, AtlasType currentElementType, Object currentValue) {
+            this.attribute = attribute;
+            this.elementType = currentElementType;
+            this.currentValue = currentValue;
+        }
+
+        public Builder(AtlasStructType.AtlasAttribute attribute, Object currentValue) {
+            this.attribute = attribute;
+            this.elementType = null;
+            this.currentValue = currentValue;
+        }
+
+        Builder referringVertex(AtlasVertex referringVertex) {
+            this.referringVertex = referringVertex;
+            return this;
+        }
+
+        Builder edge(AtlasEdge edge) {
+            this.currentEdge = Optional.of(edge);
+            return this;
+        }
+
+        Builder edge(Optional<AtlasEdge> edge) {
+            this.currentEdge = edge;
+            return this;
+        }
+
+        Builder vertexProperty(String propertyKey) {
+            this.vertexPropertyKey = propertyKey;
+            return this;
+        }
+
+        GraphMutationContext build() {
+            return new GraphMutationContext(this);
+        }
+    }
+
+    public AtlasStructType getParentType() {
+        return attribute.getStructType();
+    }
+
+    public AtlasStructDef getStructDef() {
+        return attribute.getStructDef();
+    }
+
+    public AtlasStructDef.AtlasAttributeDef getAttributeDef() {
+        return attribute.getAttributeDef();
+    }
+
+    public AtlasType getAttrType() {
+        return currentElementType == null ? attribute.getAttributeType() : currentElementType;
+    }
+
+    public AtlasType getCurrentElementType() {
+        return currentElementType;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public AtlasVertex getReferringVertex() {
+        return referringVertex;
+    }
+
+    public Optional<AtlasEdge> getCurrentEdge() {
+        return existingEdge;
+    }
+
+    public void setElementType(final AtlasType attrType) {
+        this.currentElementType = attrType;
+    }
+
+    public AtlasStructType.AtlasAttribute getAttribute() {
+        return attribute;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/HardDeleteHandlerV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/HardDeleteHandlerV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/HardDeleteHandlerV1.java
new file mode 100644
index 0000000..fe0db39
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/HardDeleteHandlerV1.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.atlas.repository.store.graph.v1;
+
+import com.google.inject.Inject;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasTypeRegistry;
+
+public class HardDeleteHandlerV1 extends DeleteHandlerV1 {
+
+    @Inject
+    public HardDeleteHandlerV1(AtlasTypeRegistry typeRegistry) {
+        super(typeRegistry, false, true);
+    }
+
+    @Override
+    protected void _deleteVertex(AtlasVertex instanceVertex, boolean force) {
+        graphHelper.removeVertex(instanceVertex);
+    }
+
+    @Override
+    protected void deleteEdge(AtlasEdge edge, boolean force) throws AtlasBaseException {
+        graphHelper.removeEdge(edge);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/IDBasedEntityResolver.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/IDBasedEntityResolver.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/IDBasedEntityResolver.java
new file mode 100644
index 0000000..488f141
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/IDBasedEntityResolver.java
@@ -0,0 +1,118 @@
+/**
+ * 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.v1;
+
+import com.google.common.base.Optional;
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
+import org.apache.atlas.repository.store.graph.EntityResolver;
+import org.apache.atlas.typesystem.exception.EntityNotFoundException;
+import org.apache.atlas.typesystem.persistence.Id;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class IDBasedEntityResolver implements EntityResolver {
+
+    private Map<String, AtlasEntity> idToEntityMap = new HashMap<>();
+
+    private final GraphHelper graphHelper = GraphHelper.getInstance();
+
+    private EntityGraphDiscoveryContext context;
+
+    @Override
+    public void init(EntityGraphDiscoveryContext context) throws AtlasBaseException {
+        this.context = context;
+        for (AtlasEntity entity : context.getRootEntities()) {
+            idToEntityMap.put(entity.getGuid(), entity);
+        }
+    }
+
+    public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException {
+
+        if ( context == null) {
+            throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Entity resolver not initialized");
+        }
+
+        List<AtlasObjectId> resolvedReferences = new ArrayList<>();
+
+        for (AtlasObjectId typeIdPair : context.getUnresolvedIdReferences()) {
+            if ( AtlasEntity.isAssigned(typeIdPair.getGuid())) {
+                //validate in graph repo that given guid, typename exists
+                Optional<AtlasVertex> vertex = resolveGuid(typeIdPair);
+
+                if ( vertex.isPresent() ) {
+                    context.addRepositoryResolvedReference(typeIdPair, vertex.get());
+                    resolvedReferences.add(typeIdPair);
+                }
+            } else {
+                //check if root references have this temporary id
+               if (!idToEntityMap.containsKey(typeIdPair.getGuid()) ) {
+                   throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, "Could not find an entity with the specified id " + typeIdPair + " in the request");
+               }
+            }
+        }
+
+        context.removeUnResolvedIdReferences(resolvedReferences);
+
+        //Resolve root references
+        for (AtlasEntity entity : context.getRootEntities()) {
+            if ( !context.isResolved(entity.getGuid()) && AtlasEntity.isAssigned(entity.getGuid())) {
+                AtlasObjectId typeIdPair = new AtlasObjectId(entity.getTypeName(), entity.getGuid());
+                Optional<AtlasVertex> vertex = resolveGuid(typeIdPair);
+                if (vertex.isPresent()) {
+                    context.addRepositoryResolvedReference(typeIdPair, vertex.get());
+                    context.removeUnResolvedIdReference(typeIdPair);
+                }
+            }
+        }
+        return context;
+    }
+
+    private Optional<AtlasVertex> resolveGuid(AtlasObjectId typeIdPair) throws AtlasBaseException {
+        //validate in graph repo that given guid, typename exists
+        AtlasVertex vertex = null;
+        try {
+            vertex = graphHelper.findVertex(Constants.GUID_PROPERTY_KEY, typeIdPair.getGuid(),
+                Constants.TYPE_NAME_PROPERTY_KEY, typeIdPair.getTypeName(),
+                Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name());
+        } catch (EntityNotFoundException e) {
+            //Ignore
+        }
+        if ( vertex != null ) {
+            return Optional.of(vertex);
+        } else {
+            throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, "Could not find an entity with the specified guid " + typeIdPair.getGuid() + " in Atlas respository");
+        }
+    }
+
+    @Override
+    public void cleanUp() throws AtlasBaseException {
+        idToEntityMap.clear();
+        this.context = null;
+    }
+
+}