Repository: atlas
Updated Branches:
  refs/heads/master 4a938d873 -> cabc1e550


ATLAS-2534: Glossary REST API (bugfix)

Change-Id: Ic0b40d722f2a797db19dd7ee95ef30866e073128


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

Branch: refs/heads/master
Commit: cabc1e55059b70cfab49e1ca960d2cdee6a3828f
Parents: 4a938d8
Author: apoorvnaik <apoorvn...@apache.org>
Authored: Mon Apr 16 14:02:31 2018 -0700
Committer: apoorvnaik <apoorvn...@apache.org>
Committed: Wed Apr 18 07:54:58 2018 -0700

----------------------------------------------------------------------
 .../java/org/apache/atlas/AtlasErrorCode.java   |   3 +
 .../atlas/glossary/GlossaryCategoryUtils.java   |  98 ++++++++----
 .../apache/atlas/glossary/GlossaryService.java  |  49 +++++-
 .../atlas/glossary/GlossaryTermUtils.java       |  95 ++++++++----
 .../apache/atlas/glossary/GlossaryUtils.java    |   7 +-
 .../store/graph/v1/EntityGraphRetriever.java    |   8 +-
 .../atlas/glossary/GlossaryServiceTest.java     | 153 +++++++++++--------
 .../org/apache/atlas/web/rest/GlossaryREST.java |   3 +
 8 files changed, 278 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java 
b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
index bbb1b1a..3efe41c 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -168,6 +168,9 @@ public enum AtlasErrorCode {
     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"),
     SAVED_SEARCH_ALREADY_EXISTS(409, "ATLAS-409-00-006", "search named {0} 
already exists for user {1}"),
+    GLOSSARY_ALREADY_EXISTS(409, "ATLAS-409-00-007", "Glossary with 
qualifiedName {0} already exists"),
+    GLOSSARY_TERM_ALREADY_EXISTS(409, "ATLAS-409-00-009", "Glossary term with 
qualifiedName {0} already exists"),
+    GLOSSARY_CATEGORY_ALREADY_EXISTS(409, "ATLAS-409-00-00A", "Glossary 
category with qualifiedName {0} already exists"),
 
     // All internal errors go here
     INTERNAL_ERROR(500, "ATLAS-500-00-001", "Internal server error {0}"),

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java
index 46d8889..1423b98 100644
--- 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java
+++ 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java
@@ -29,9 +29,13 @@ import 
org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
 import org.apache.atlas.type.AtlasRelationshipType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -96,8 +100,8 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void processParentCategory(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
-        AtlasRelatedCategoryHeader newParent      = newObj.getParentCategory();
+    private void processParentCategory(AtlasGlossaryCategory updatedCategory, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        AtlasRelatedCategoryHeader newParent      = 
updatedCategory.getParentCategory();
         AtlasRelatedCategoryHeader existingParent = 
existing.getParentCategory();
         switch (op) {
             case CREATE:
@@ -152,9 +156,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void processAssociatedTerms(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
-        Set<AtlasRelatedTermHeader> newTerms      = newObj.getTerms();
-        Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
+    private void processAssociatedTerms(AtlasGlossaryCategory updatedCategory, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        Map<String, AtlasRelatedTermHeader> newTerms      = 
getTerms(updatedCategory);
+        Map<String, AtlasRelatedTermHeader> existingTerms = getTerms(existing);
 
         switch (op) {
             case CREATE:
@@ -162,51 +166,66 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
                     LOG.debug("Creating term relation with category = {}, 
terms = {}", existing.getDisplayName(),
                               Objects.nonNull(newTerms) ? newTerms.size() : 
"none");
                 }
-                createTermCategorizationRelationships(existing, newTerms);
+                createTermCategorizationRelationships(existing, 
newTerms.values());
                 break;
             case UPDATE:
-                if (CollectionUtils.isEmpty(existingTerms)) {
+                if (MapUtils.isEmpty(existingTerms)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Creating term relation with category = {}, 
terms = {}", existing.getDisplayName(),
                                   Objects.nonNull(newTerms) ? newTerms.size() 
: "none");
                     }
-                    createTermCategorizationRelationships(existing, newTerms);
+                    createTermCategorizationRelationships(existing, 
newTerms.values());
                     break;
                 }
 
-                if (CollectionUtils.isEmpty(newTerms)) {
+                if (MapUtils.isEmpty(newTerms)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Deleting term relation with category = {}, 
terms = {}", existing.getDisplayName(), existingTerms.size());
                     }
-                    deleteTermCategorizationRelationships(existing, 
existingTerms);
+                    deleteTermCategorizationRelationships(existing, 
existingTerms.values());
                     break;
                 }
 
                 Set<AtlasRelatedTermHeader> toCreate = newTerms
+                                                               .values()
                                                                .stream()
-                                                               .filter(c -> 
Objects.isNull(c.getRelationGuid()))
+                                                               .filter(t -> 
!existingTerms.containsKey(t.getTermGuid()))
                                                                
.collect(Collectors.toSet());
                 createTermCategorizationRelationships(existing, toCreate);
 
                 Set<AtlasRelatedTermHeader> toUpdate = newTerms
+                                                               .values()
                                                                .stream()
-                                                               .filter(c -> 
Objects.nonNull(c.getRelationGuid()) && existingTerms.contains(c))
+                                                               .filter(t -> 
updatedExistingTermRelation(existingTerms, t))
                                                                
.collect(Collectors.toSet());
                 updateTermCategorizationRelationships(existing, toUpdate);
 
                 Set<AtlasRelatedTermHeader> toDelete = existingTerms
+                                                               .values()
                                                                .stream()
-                                                               .filter(c -> 
!toCreate.contains(c) && !toUpdate.contains(c))
+                                                               .filter(t -> 
!newTerms.containsKey(t.getTermGuid()))
                                                                
.collect(Collectors.toSet());
                 deleteTermCategorizationRelationships(existing, toDelete);
                 break;
             case DELETE:
-                deleteTermCategorizationRelationships(existing, existingTerms);
+                deleteTermCategorizationRelationships(existing, 
existingTerms.values());
                 break;
         }
     }
 
-    private void createTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+    private boolean updatedExistingTermRelation(Map<String, 
AtlasRelatedTermHeader> existingTerms, AtlasRelatedTermHeader term) {
+        return Objects.nonNull(term.getRelationGuid()) && 
!existingTerms.get(term.getTermGuid()).equals(term);
+    }
+
+    private Map<String, AtlasRelatedTermHeader> getTerms(final 
AtlasGlossaryCategory category) {
+        return Objects.nonNull(category.getTerms()) ?
+                       category.getTerms()
+                               .stream()
+                               
.collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid, t -> t)) :
+                       Collections.EMPTY_MAP;
+    }
+
+    private void createTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
             Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
             for (AtlasRelatedTermHeader term : terms) {
@@ -228,7 +247,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void updateTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+    private void updateTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
             for (AtlasRelatedTermHeader term : terms) {
                 if (DEBUG_ENABLED) {
@@ -241,7 +260,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void deleteTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+    private void deleteTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
             for (AtlasRelatedTermHeader term : terms) {
                 if (DEBUG_ENABLED) {
@@ -252,61 +271,76 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void processCategoryChildren(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
-        Set<AtlasRelatedCategoryHeader> newChildren      = 
newObj.getChildrenCategories();
-        Set<AtlasRelatedCategoryHeader> existingChildren = 
existing.getChildrenCategories();
+    private void processCategoryChildren(AtlasGlossaryCategory 
updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) 
throws AtlasBaseException {
+        Map<String, AtlasRelatedCategoryHeader> newChildren      = 
getChildren(updatedCategory);
+        Map<String, AtlasRelatedCategoryHeader> existingChildren = 
getChildren(existing);
         switch (op) {
             case CREATE:
                 if (DEBUG_ENABLED) {
                     LOG.debug("Creating new children, category = {}, children 
= {}", existing.getDisplayName(),
                               Objects.nonNull(newChildren) ? 
newChildren.size() : "none");
                 }
-                createCategoryRelationships(existing, newChildren);
+                createCategoryRelationships(existing, newChildren.values());
                 break;
             case UPDATE:
                 // Create new children
-                if (CollectionUtils.isEmpty(existingChildren)) {
+                if (MapUtils.isEmpty(existingChildren)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Creating new children, category = {}, 
children = {}", existing.getDisplayName(),
                                   Objects.nonNull(newChildren) ? 
newChildren.size() : "none");
                     }
-                    createCategoryRelationships(existing, newChildren);
+                    createCategoryRelationships(existing, 
newChildren.values());
                     break;
                 }
                 // Delete current children
-                if (CollectionUtils.isEmpty(newChildren)) {
+                if (MapUtils.isEmpty(newChildren)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Deleting children, category = {}, children 
= {}", existing.getDisplayName(), existingChildren.size());
                     }
-                    deleteCategoryRelationships(existing, existingChildren);
+                    deleteCategoryRelationships(existing, 
existingChildren.values());
                     break;
                 }
 
                 Set<AtlasRelatedCategoryHeader> toCreate = newChildren
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(c 
-> Objects.isNull(c.getRelationGuid()))
+                                                                   .filter(c 
-> !existingChildren.containsKey(c.getCategoryGuid()))
                                                                    
.collect(Collectors.toSet());
                 createCategoryRelationships(existing, toCreate);
 
                 Set<AtlasRelatedCategoryHeader> toUpdate = newChildren
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(c 
-> Objects.nonNull(c.getRelationGuid()) && existingChildren.contains(c))
+                                                                   .filter(c 
-> updatedExistingCategoryRelation(existingChildren, c))
                                                                    
.collect(Collectors.toSet());
                 updateCategoryRelationships(existing, toUpdate);
 
                 Set<AtlasRelatedCategoryHeader> toDelete = existingChildren
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(c 
-> !toCreate.contains(c) && !toUpdate.contains(c))
+                                                                   .filter(c 
-> !newChildren.containsKey(c.getCategoryGuid()))
                                                                    
.collect(Collectors.toSet());
                 deleteCategoryRelationships(existing, toDelete);
                 break;
             case DELETE:
-                deleteCategoryRelationships(existing, existingChildren);
+                deleteCategoryRelationships(existing, 
existingChildren.values());
                 break;
         }
     }
 
-    private void createCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException {
+    private boolean updatedExistingCategoryRelation(Map<String, 
AtlasRelatedCategoryHeader> existingChildren, AtlasRelatedCategoryHeader 
header) {
+        return Objects.nonNull(header.getRelationGuid()) && 
!header.equals(existingChildren.get(header.getCategoryGuid()));
+    }
+
+    private Map<String, AtlasRelatedCategoryHeader> getChildren(final 
AtlasGlossaryCategory category) {
+        return Objects.nonNull(category.getChildrenCategories()) ?
+                       category.getChildrenCategories()
+                               .stream()
+                               
.collect(Collectors.toMap(AtlasRelatedCategoryHeader::getCategoryGuid, c -> c)) 
:
+                       Collections.EMPTY_MAP;
+    }
+
+    private void createCategoryRelationships(AtlasGlossaryCategory existing, 
Collection<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(newChildren)) {
             Set<AtlasRelatedCategoryHeader> existingChildren = 
existing.getChildrenCategories();
             for (AtlasRelatedCategoryHeader child : newChildren) {
@@ -324,7 +358,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void updateCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException {
+    private void updateCategoryRelationships(AtlasGlossaryCategory existing, 
Collection<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(toUpdate)) {
             for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) {
                 if (DEBUG_ENABLED) {
@@ -337,7 +371,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
         }
     }
 
-    private void deleteCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException {
+    private void deleteCategoryRelationships(AtlasGlossaryCategory existing, 
Collection<AtlasRelatedCategoryHeader> existingChildren) throws 
AtlasBaseException {
         if (CollectionUtils.isNotEmpty(existingChildren)) {
             for (AtlasRelatedCategoryHeader child : existingChildren) {
                 if (DEBUG_ENABLED) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
index 9fd795b..5db0bb0 100644
--- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
@@ -27,6 +27,7 @@ import 
org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
 import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
 import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
 import org.apache.atlas.model.instance.AtlasRelatedObjectId;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.ogm.DataAccess;
 import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
@@ -53,13 +54,17 @@ public class GlossaryService {
     private static final Logger  LOG           = 
LoggerFactory.getLogger(GlossaryService.class);
     private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
 
-    private final DataAccess             dataAccess;
-    private final GlossaryTermUtils      glossaryTermUtils;
-    private final GlossaryCategoryUtils  glossaryCategoryUtils;
+    private static final String QUALIFIED_NAME_ATTR              = 
"qualifiedName";
+
+    private final DataAccess            dataAccess;
+    private final GlossaryTermUtils     glossaryTermUtils;
+    private final GlossaryCategoryUtils glossaryCategoryUtils;
+    private final AtlasTypeRegistry     atlasTypeRegistry;
 
     @Inject
     public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore 
relationshipStore, final AtlasTypeRegistry typeRegistry) {
         this.dataAccess = dataAccess;
+        this.atlasTypeRegistry = typeRegistry;
         glossaryTermUtils = new GlossaryTermUtils(relationshipStore, 
typeRegistry);
         glossaryCategoryUtils = new GlossaryCategoryUtils(relationshipStore, 
typeRegistry);
     }
@@ -78,7 +83,7 @@ public class GlossaryService {
             LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, 
offset, sortOrder);
         }
 
-        List<String>     glossaryGuids    = 
AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_PREFIX, 
sortOrder);
+        List<String>     glossaryGuids    = 
AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME, 
sortOrder);
         PaginationHelper paginationHelper = new 
PaginationHelper<>(glossaryGuids, offset, limit);
 
         List<AtlasGlossary> ret;
@@ -118,6 +123,7 @@ public class GlossaryService {
         if (Objects.isNull(atlasGlossary)) {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary 
definition missing");
         }
+
         if (StringUtils.isEmpty(atlasGlossary.getQualifiedName())) {
             if (StringUtils.isEmpty(atlasGlossary.getDisplayName())) {
                 throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED);
@@ -125,11 +131,17 @@ public class GlossaryService {
                 atlasGlossary.setQualifiedName(atlasGlossary.getDisplayName());
             }
         }
+
+        if (glossaryExists(atlasGlossary)) {
+            throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_ALREADY_EXISTS, 
atlasGlossary.getQualifiedName());
+        }
+
         AtlasGlossary saved = dataAccess.save(atlasGlossary);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.createGlossary() : {}", saved);
         }
+
         return saved;
     }
 
@@ -297,6 +309,10 @@ public class GlossaryService {
             }
         }
 
+        if (termExists(glossaryTerm)) {
+            throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_ALREADY_EXISTS, 
glossaryTerm.getQualifiedName());
+        }
+
         AtlasGlossaryTerm existing = dataAccess.save(glossaryTerm);
         glossaryTermUtils.processTermRelations(glossaryTerm, existing, 
GlossaryUtils.RelationshipOperation.CREATE);
 
@@ -457,6 +473,10 @@ public class GlossaryService {
             }
         }
 
+        if (categoryExists(glossaryCategory)) {
+            throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_ALREADY_EXISTS, 
glossaryCategory.getQualifiedName());
+        }
+
         AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory);
 
         // Attempt relation creation
@@ -726,6 +746,27 @@ public class GlossaryService {
         return glossary;
     }
 
+    private boolean glossaryExists(AtlasGlossary atlasGlossary) {
+        AtlasVertex vertex = 
AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME),
 new HashMap<String, Object>() {{
+            put(QUALIFIED_NAME_ATTR, atlasGlossary.getQualifiedName());
+        }});
+        return Objects.nonNull(vertex);
+    }
+
+    private boolean termExists(AtlasGlossaryTerm term) {
+        AtlasVertex vertex = 
AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TERM_TYPENAME),
 new HashMap<String, Object>() {{
+            put(QUALIFIED_NAME_ATTR, term.getQualifiedName());
+        }});
+        return Objects.nonNull(vertex);
+    }
+
+    private boolean categoryExists(AtlasGlossaryCategory category) {
+        AtlasVertex vertex = 
AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_CATEGORY_TYPENAME),
 new HashMap<String, Object>() {{
+            put(QUALIFIED_NAME_ATTR, category.getQualifiedName());
+        }});
+        return Objects.nonNull(vertex);
+    }
+
     private void deleteCategories(final AtlasGlossary existing, final 
Set<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(categories)) {
             if (DEBUG_ENABLED) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java
index c2d2d2b..803fad6 100644
--- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java
@@ -31,10 +31,12 @@ import 
org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
 import org.apache.atlas.type.AtlasRelationshipType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -170,39 +172,42 @@ public class GlossaryTermUtils extends GlossaryUtils {
                 break;
             case UPDATE:
                 for (AtlasGlossaryTerm.Relation relation : 
AtlasGlossaryTerm.Relation.values()) {
-                    Set<AtlasRelatedTermHeader> existingTermHeaders = 
existingRelatedTerms.get(relation);
-                    Set<AtlasRelatedTermHeader> newTermHeaders      = 
newRelatedTerms.get(relation);
+                    Map<String, AtlasRelatedTermHeader> existingTermHeaders = 
getRelatedTermHeaders(existingRelatedTerms, relation);
+                    Map<String, AtlasRelatedTermHeader> newTermHeaders      = 
getRelatedTermHeaders(newRelatedTerms, relation);
 
                     // No existing term relations, create all
-                    if (CollectionUtils.isEmpty(existingTermHeaders)) {
+                    if (MapUtils.isEmpty(existingTermHeaders)) {
                         if (DEBUG_ENABLED) {
                             LOG.debug("Creating new term relations, relation = 
{}, terms = {}", relation,
                                       Objects.nonNull(newTermHeaders) ? 
newTermHeaders.size() : "none");
                         }
-                        createTermRelationships(existing, relation, 
newTermHeaders);
+                        createTermRelationships(existing, relation, 
newTermHeaders.values());
                         continue;
                     }
 
                     // Existing term relations but nothing in updated object, 
remove all
-                    if (CollectionUtils.isEmpty(newTermHeaders)) {
+                    if (MapUtils.isEmpty(newTermHeaders)) {
                         if (DEBUG_ENABLED) {
                             LOG.debug("Deleting existing term relations, 
relation = {}, terms = {}", relation, existingTermHeaders.size());
                         }
-                        deleteTermRelationships(relation, existingTermHeaders);
+                        deleteTermRelationships(relation, 
existingTermHeaders.values());
                         continue;
                     }
                     // Determine what to update, delete or create
                     Set<AtlasRelatedTermHeader> toCreate = newTermHeaders
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(t 
-> Objects.isNull(t.getRelationGuid()))
+                                                                   .filter(t 
-> !existingTermHeaders.containsKey(t.getTermGuid()))
                                                                    
.collect(Collectors.toSet());
                     Set<AtlasRelatedTermHeader> toUpdate = newTermHeaders
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(t 
-> Objects.nonNull(t.getRelationGuid()) && existingTermHeaders.contains(t))
+                                                                   .filter(t 
-> updatedExistingTermRelation(existingTermHeaders, t))
                                                                    
.collect(Collectors.toSet());
                     Set<AtlasRelatedTermHeader> toDelete = existingTermHeaders
+                                                                   .values()
                                                                    .stream()
-                                                                   .filter(t 
-> !toCreate.contains(t) && !toUpdate.contains(t))
+                                                                   .filter(t 
-> !newTermHeaders.containsKey(t.getTermGuid()))
                                                                    
.collect(Collectors.toSet());
 
                     createTermRelationships(existing, relation, toCreate);
@@ -221,61 +226,88 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void processAssociatedCategories(AtlasGlossaryTerm newObj, 
AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException 
{
-        Set<AtlasTermCategorizationHeader> newCategories      = 
newObj.getCategories();
-        Set<AtlasTermCategorizationHeader> existingCategories = 
existing.getCategories();
+    private Map<String, AtlasRelatedTermHeader> 
getRelatedTermHeaders(Map<AtlasGlossaryTerm.Relation, 
Set<AtlasRelatedTermHeader>> relatedTerms, AtlasGlossaryTerm.Relation relation) 
{
+        return Objects.nonNull(relatedTerms.get(relation)) ?
+                       relatedTerms.get(relation)
+                                   .stream()
+                                   
.collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid, t -> t)) :
+                       Collections.EMPTY_MAP;
+    }
+
+    private boolean updatedExistingTermRelation(Map<String, 
AtlasRelatedTermHeader> existingTermHeaders, AtlasRelatedTermHeader header) {
+        return Objects.nonNull(header.getRelationGuid()) && 
!header.equals(existingTermHeaders.get(header.getTermGuid()));
+    }
+
+    private void processAssociatedCategories(AtlasGlossaryTerm updatedTerm, 
AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException 
{
+        Map<String, AtlasTermCategorizationHeader> newCategories      = 
getAssociatedCategories(updatedTerm);
+        Map<String, AtlasTermCategorizationHeader> existingCategories = 
getAssociatedCategories(existing);
         switch (op) {
             case CREATE:
                 if (Objects.nonNull(newCategories)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Creating new term categorization, term = 
{}, categories = {}", existing.getGuid(), newCategories.size());
                     }
-                    createTermCategorizationRelationships(existing, 
newCategories);
+                    createTermCategorizationRelationships(existing, 
newCategories.values());
                 }
                 break;
             case UPDATE:
                 // If no existing categories are present then create all 
existing ones
-                if (CollectionUtils.isEmpty(existingCategories)) {
+                if (MapUtils.isEmpty(existingCategories)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Creating new term categorization, term = 
{}, categories = {}", existing.getGuid(),
                                   Objects.nonNull(newCategories) ? 
newCategories.size() : "none");
                     }
-                    createTermCategorizationRelationships(existing, 
newCategories);
+                    createTermCategorizationRelationships(existing, 
newCategories.values());
                     break;
                 }
 
                 // If no new categories are present then delete all existing 
ones
-                if (CollectionUtils.isEmpty(newCategories)) {
+                if (MapUtils.isEmpty(newCategories)) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Deleting term categorization, term = {}, 
categories = {}", existing.getGuid(), existingCategories.size());
                     }
-                    deleteCategorizationRelationship(existingCategories);
+                    
deleteCategorizationRelationship(existingCategories.values());
                     break;
                 }
 
                 Set<AtlasTermCategorizationHeader> toCreate = newCategories
+                                                                      .values()
                                                                       .stream()
-                                                                      
.filter(c -> Objects.isNull(c.getRelationGuid()))
+                                                                      
.filter(c -> !existingCategories.containsKey(c.getCategoryGuid()))
                                                                       
.collect(Collectors.toSet());
                 createTermCategorizationRelationships(existing, toCreate);
                 Set<AtlasTermCategorizationHeader> toUpdate = newCategories
+                                                                      .values()
                                                                       .stream()
-                                                                      
.filter(c -> Objects.nonNull(c.getRelationGuid()) && 
existingCategories.contains(c))
+                                                                      
.filter(c -> updatedExistingCategorizationRelation(existingCategories, c))
                                                                       
.collect(Collectors.toSet());
                 updateTermCategorizationRelationships(existing, toUpdate);
                 Set<AtlasTermCategorizationHeader> toDelete = 
existingCategories
+                                                                      .values()
                                                                       .stream()
-                                                                      
.filter(c -> !toCreate.contains(c) && !toUpdate.contains(c))
+                                                                      
.filter(c -> !newCategories.containsKey(c.getCategoryGuid()))
                                                                       
.collect(Collectors.toSet());
                 deleteCategorizationRelationship(toDelete);
                 break;
             case DELETE:
-                deleteCategorizationRelationship(existingCategories);
+                deleteCategorizationRelationship(existingCategories.values());
                 break;
         }
     }
 
-    private void createTermCategorizationRelationships(AtlasGlossaryTerm 
existing, Set<AtlasTermCategorizationHeader> categories) throws 
AtlasBaseException {
+    private boolean updatedExistingCategorizationRelation(Map<String, 
AtlasTermCategorizationHeader> existingCategories, 
AtlasTermCategorizationHeader header) {
+        return Objects.nonNull(header.getRelationGuid()) && 
!header.equals(existingCategories.get(header.getCategoryGuid()));
+    }
+
+    private Map<String, AtlasTermCategorizationHeader> 
getAssociatedCategories(final AtlasGlossaryTerm term) {
+        return Objects.nonNull(term.getCategories()) ?
+                       term.getCategories()
+                           .stream()
+                           
.collect(Collectors.toMap(AtlasTermCategorizationHeader::getCategoryGuid, c -> 
c)) :
+                       Collections.EMPTY_MAP;
+    }
+
+    private void createTermCategorizationRelationships(AtlasGlossaryTerm 
existing, Collection<AtlasTermCategorizationHeader> categories) throws 
AtlasBaseException {
         if (CollectionUtils.isNotEmpty(categories)) {
             Set<AtlasTermCategorizationHeader> existingCategories = 
existing.getCategories();
             for (AtlasTermCategorizationHeader categorizationHeader : 
categories) {
@@ -293,7 +325,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void updateTermCategorizationRelationships(AtlasGlossaryTerm 
existing, Set<AtlasTermCategorizationHeader> toUpdate) throws 
AtlasBaseException {
+    private void updateTermCategorizationRelationships(AtlasGlossaryTerm 
existing, Collection<AtlasTermCategorizationHeader> toUpdate) throws 
AtlasBaseException {
         if (CollectionUtils.isNotEmpty(toUpdate)) {
             for (AtlasTermCategorizationHeader categorizationHeader : 
toUpdate) {
                 if (DEBUG_ENABLED) {
@@ -306,7 +338,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void 
deleteCategorizationRelationship(Set<AtlasTermCategorizationHeader> 
existingCategories) throws AtlasBaseException {
+    private void 
deleteCategorizationRelationship(Collection<AtlasTermCategorizationHeader> 
existingCategories) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(existingCategories)) {
             for (AtlasTermCategorizationHeader categorizationHeader : 
existingCategories) {
                 if (DEBUG_ENABLED) {
@@ -317,11 +349,16 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void createTermRelationships(AtlasGlossaryTerm existing, 
AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws 
AtlasBaseException {
+    private void createTermRelationships(AtlasGlossaryTerm existing, 
AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) 
throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
-            Set<AtlasRelatedTermHeader> existingRelations = 
existing.getRelatedTerms().get(relation);
+            Map<String, AtlasRelatedTermHeader> existingRelations;
+            if (Objects.nonNull(existing.getRelatedTerms()) && 
Objects.nonNull(existing.getRelatedTerms().get(relation))) {
+                existingRelations = 
existing.getRelatedTerms().get(relation).stream().collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid,
 t -> t));
+            } else {
+                existingRelations = Collections.EMPTY_MAP;
+            }
             for (AtlasRelatedTermHeader term : terms) {
-                if (Objects.nonNull(existingRelations) && 
existingRelations.contains(term)) {
+                if (Objects.nonNull(existingRelations) && 
existingRelations.containsKey(term.getTermGuid())) {
                     if (DEBUG_ENABLED) {
                         LOG.debug("Skipping existing term relation 
termGuid={}", term.getTermGuid());
                     }
@@ -335,7 +372,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void updateTermRelationships(AtlasGlossaryTerm.Relation relation, 
Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+    private void updateTermRelationships(AtlasGlossaryTerm.Relation relation, 
Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
             for (AtlasRelatedTermHeader term : terms) {
                 if (DEBUG_ENABLED) {
@@ -348,7 +385,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
         }
     }
 
-    private void deleteTermRelationships(AtlasGlossaryTerm.Relation relation, 
Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+    private void deleteTermRelationships(AtlasGlossaryTerm.Relation relation, 
Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(terms)) {
             for (AtlasRelatedTermHeader termHeader : terms) {
                 if (DEBUG_ENABLED) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java
index 38555cc..ec8a1dc 100644
--- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java
@@ -36,8 +36,12 @@ public abstract class GlossaryUtils {
     public static final String TERM_ASSIGNMENT_ATTR_STEWARD     = "steward";
     public static final String TERM_ASSIGNMENT_ATTR_SOURCE      = "source";
 
-    static final String ATLAS_GLOSSARY_PREFIX = "__AtlasGlossary";
+    static final String ATLAS_GLOSSARY_TYPENAME          = "__AtlasGlossary";
+    static final String ATLAS_GLOSSARY_TERM_TYPENAME     = 
"__AtlasGlossaryTerm";
+    static final String ATLAS_GLOSSARY_CATEGORY_TYPENAME = 
"__AtlasGlossaryCategory";
+
     // Relation name constants
+    protected static final String ATLAS_GLOSSARY_PREFIX          = 
ATLAS_GLOSSARY_TYPENAME;
     protected static final String TERM_ANCHOR                    = 
ATLAS_GLOSSARY_PREFIX + "TermAnchor";
     protected static final String CATEGORY_ANCHOR                = 
ATLAS_GLOSSARY_PREFIX + "CategoryAnchor";
     protected static final String CATEGORY_HIERARCHY             = 
ATLAS_GLOSSARY_PREFIX + "CategoryHierarchyLink";
@@ -49,7 +53,6 @@ public abstract class GlossaryUtils {
     protected static final String TERM_RELATION_ATTR_SOURCE      = "source";
     protected static final String TERM_RELATION_ATTR_STATUS      = "status";
 
-
     protected final AtlasRelationshipStore relationshipStore;
     protected final AtlasTypeRegistry typeRegistry;
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
index 57c9135..23ffdcd 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
@@ -500,12 +500,8 @@ public final class EntityGraphRetriever {
         Iterable edges = 
entityVertex.query().direction(AtlasEdgeDirection.IN).label(TERM_ASSIGNMENT_LABEL).edges();
 
         if (edges != null) {
-            Iterator<AtlasEdge> iterator = edges.iterator();
-
-            while (iterator.hasNext()) {
-                AtlasEdge edge = iterator.next();
-
-                if (edge != null) {
+            for (final AtlasEdge edge : (Iterable<AtlasEdge>) edges) {
+                if (edge != null && GraphHelper.getStatus(edge) != 
AtlasEntity.Status.DELETED) {
                     ret.add(toTermAssignmentHeader(edge));
                 }
             }

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java
----------------------------------------------------------------------
diff --git 
a/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java 
b/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java
index 0294550..6deef80 100644
--- 
a/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java
+++ 
b/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java
@@ -39,6 +39,7 @@ import 
org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
 import org.apache.atlas.store.AtlasTypeDefStore;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.atlas.utils.AtlasJson;
+import org.apache.commons.collections.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.SkipException;
@@ -55,10 +56,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.fail;
+import static org.testng.Assert.*;
 
 @Guice(modules = TestModules.TestOnlyModule.class)
 public class GlossaryServiceTest {
@@ -96,10 +94,8 @@ public class GlossaryServiceTest {
         } catch (AtlasBaseException | IOException e) {
             throw new SkipException("SubjectArea model loading failed");
         }
-    }
 
-    @Test(groups = "Glossary.CREATE")
-    public void testCreateGlossary() {
+        // Glossary
         bankGlossary = new AtlasGlossary();
         bankGlossary.setQualifiedName("testBankingGlossary");
         bankGlossary.setDisplayName("Banking glossary");
@@ -116,34 +112,26 @@ public class GlossaryServiceTest {
         creditUnionGlossary.setUsage("N/A");
         creditUnionGlossary.setLanguage("en-US");
 
-        try {
-            AtlasGlossary created = 
glossaryService.createGlossary(bankGlossary);
-            bankGlossary.setGuid(created.getGuid());
-            created = glossaryService.createGlossary(creditUnionGlossary);
-            creditUnionGlossary.setGuid(created.getGuid());
-        } catch (AtlasBaseException e) {
-            fail("Glossary creation should've succeeded", e);
-        }
-
-        // Glossary anchor
-        AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader();
-        glossaryId.setGlossaryGuid(bankGlossary.getGuid());
-
-        // Create a category
+        // Category
         accountCategory = new AtlasGlossaryCategory();
         accountCategory.setQualifiedName("acc@testBankingGlossary");
         accountCategory.setDisplayName("Account categorization");
         accountCategory.setShortDescription("Short description");
         accountCategory.setLongDescription("Long description");
-        accountCategory.setAnchor(glossaryId);
 
-        try {
-            accountCategory = glossaryService.createCategory(accountCategory);
-        } catch (AtlasBaseException e) {
-            fail("Account category creation should've succeeded");
-        }
+        customerCategory = new AtlasGlossaryCategory();
+        customerCategory.setQualifiedName("customer@testBankingGlossary");
+        customerCategory.setDisplayName("Customer category");
+        customerCategory.setShortDescription("Short description");
+        customerCategory.setLongDescription("Long description");
 
-        // Create terms
+        mortgageCategory = new AtlasGlossaryCategory();
+        mortgageCategory.setQualifiedName("mtg@testBankingGlossary");
+        mortgageCategory.setDisplayName("Mortgage categorization");
+        mortgageCategory.setShortDescription("Short description");
+        mortgageCategory.setLongDescription("Long description");
+
+        // Terms
         checkingAccount = new AtlasGlossaryTerm();
         checkingAccount.setQualifiedName("chk_acc@testBankingGlossary");
         checkingAccount.setDisplayName("A checking account");
@@ -152,7 +140,6 @@ public class GlossaryServiceTest {
         checkingAccount.setAbbreviation("CHK");
         checkingAccount.setExamples(Arrays.asList("Personal", "Joint"));
         checkingAccount.setUsage("N/A");
-        checkingAccount.setAnchor(glossaryId);
 
         savingsAccount = new AtlasGlossaryTerm();
         savingsAccount.setQualifiedName("sav_acc@testBankingGlossary");
@@ -162,7 +149,6 @@ public class GlossaryServiceTest {
         savingsAccount.setAbbreviation("SAV");
         savingsAccount.setExamples(Arrays.asList("Personal", "Joint"));
         savingsAccount.setUsage("N/A");
-        savingsAccount.setAnchor(glossaryId);
 
         fixedRateMortgage = new AtlasGlossaryTerm();
         fixedRateMortgage.setQualifiedName("fixed_mtg@testBankingGlossary");
@@ -172,7 +158,6 @@ public class GlossaryServiceTest {
         fixedRateMortgage.setAbbreviation("FMTG");
         fixedRateMortgage.setExamples(Arrays.asList("15-yr", "30-yr"));
         fixedRateMortgage.setUsage("N/A");
-        fixedRateMortgage.setAnchor(glossaryId);
 
         adjustableRateMortgage = new AtlasGlossaryTerm();
         adjustableRateMortgage.setQualifiedName("arm_mtg@testBankingGlossary");
@@ -182,25 +167,53 @@ public class GlossaryServiceTest {
         adjustableRateMortgage.setAbbreviation("ARMTG");
         adjustableRateMortgage.setExamples(Arrays.asList("5/1", "7/1", 
"10/1"));
         adjustableRateMortgage.setUsage("N/A");
+
+
+    }
+
+    @Test(groups = "Glossary.CREATE")
+    public void testCreateGlossary() {
+        try {
+            AtlasGlossary created = 
glossaryService.createGlossary(bankGlossary);
+            bankGlossary.setGuid(created.getGuid());
+            created = glossaryService.createGlossary(creditUnionGlossary);
+            creditUnionGlossary.setGuid(created.getGuid());
+        } catch (AtlasBaseException e) {
+            fail("Glossary creation should've succeeded", e);
+        }
+
+        // Duplicate create calls should fail with 409 Conflict
+        try {
+            glossaryService.createGlossary(bankGlossary);
+            fail("Glossary duplicate creation should've failed");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode(), 
AtlasErrorCode.GLOSSARY_ALREADY_EXISTS);
+        }
+        try {
+            glossaryService.createGlossary(creditUnionGlossary);
+            fail("Glossary duplicate creation should've failed");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode(), 
AtlasErrorCode.GLOSSARY_ALREADY_EXISTS);
+        }
+
+        // Glossary anchor
+        AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader();
+        glossaryId.setGlossaryGuid(bankGlossary.getGuid());
+
+        // Create terms
+        checkingAccount.setAnchor(glossaryId);
+        savingsAccount.setAnchor(glossaryId);
+        fixedRateMortgage.setAnchor(glossaryId);
+
         adjustableRateMortgage.setAnchor(glossaryId);
 
         // Create glossary categories
-        customerCategory = new AtlasGlossaryCategory();
-        customerCategory.setQualifiedName("customer@testBankingGlossary");
-        customerCategory.setDisplayName("Customer category");
-        customerCategory.setShortDescription("Short description");
-        customerCategory.setLongDescription("Long description");
+        accountCategory.setAnchor(glossaryId);
         customerCategory.setAnchor(glossaryId);
-
-        mortgageCategory = new AtlasGlossaryCategory();
-        mortgageCategory.setQualifiedName("mtg@testBankingGlossary");
-        mortgageCategory.setDisplayName("Mortgage categorization");
-        mortgageCategory.setShortDescription("Short description");
-        mortgageCategory.setLongDescription("Long description");
         mortgageCategory.setAnchor(glossaryId);
     }
 
-    @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary")
+    @Test(groups = "Glossary.CREATE" , dependsOnMethods = 
"testCategoryCreation")
     public void testTermCreationWithoutAnyRelations() {
         try {
             checkingAccount = glossaryService.createTerm(checkingAccount);
@@ -231,11 +244,11 @@ public class GlossaryServiceTest {
         }
     }
 
-    @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary")
+    @Test(groups = "Glossary.CREATE" , dependsOnMethods = 
"testCategoryCreation")
     public void testTermCreationWithCategory() {
         try {
             AtlasTermCategorizationHeader termCategorizationHeader = new 
AtlasTermCategorizationHeader();
-            
termCategorizationHeader.setCategoryGuid(accountCategory.getGuid());
+            
termCategorizationHeader.setCategoryGuid(mortgageCategory.getGuid());
             termCategorizationHeader.setDescription("Test description");
             
termCategorizationHeader.setStatus(AtlasTermRelationshipStatus.DRAFT);
 
@@ -253,8 +266,16 @@ public class GlossaryServiceTest {
     @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary")
     public void testCategoryCreation() {
         try {
-            List<AtlasGlossaryCategory> categories = 
glossaryService.createCategories(Arrays.asList(customerCategory, 
mortgageCategory));
-            customerCategory.setGuid(categories.get(0).getGuid());
+            customerCategory = 
glossaryService.createCategory(customerCategory);
+
+            AtlasRelatedCategoryHeader parentHeader = new 
AtlasRelatedCategoryHeader();
+            parentHeader.setCategoryGuid(customerCategory.getGuid());
+
+            // Test parent relation
+            accountCategory.setParentCategory(parentHeader);
+            List<AtlasGlossaryCategory> categories = 
glossaryService.createCategories(Arrays.asList(accountCategory, 
mortgageCategory));
+
+            accountCategory.setGuid(categories.get(0).getGuid());
             mortgageCategory.setGuid(categories.get(1).getGuid());
         } catch (AtlasBaseException e) {
             fail("Category creation should've succeeded", e);
@@ -390,15 +411,21 @@ public class GlossaryServiceTest {
             savingsAccount = glossaryService.getTerm(savingsAccount.getGuid());
 
             checkingAccount.setAnchor(newGlossaryHeader);
+            checkingAccount.setSeeAlso(null);
             savingsAccount.setAnchor(newGlossaryHeader);
+            savingsAccount.setSeeAlso(null);
 
         } catch (AtlasBaseException e) {
             fail("Term fetch for migration should've succeeded", e);
         }
 
         try {
-            glossaryService.updateTerm(checkingAccount);
-            glossaryService.updateTerm(savingsAccount);
+            checkingAccount = glossaryService.updateTerm(checkingAccount);
+            assertNotNull(checkingAccount);
+            assertTrue(CollectionUtils.isEmpty(checkingAccount.getSeeAlso()));
+            savingsAccount = glossaryService.updateTerm(savingsAccount);
+            assertNotNull(savingsAccount);
+            assertTrue(CollectionUtils.isEmpty(savingsAccount.getSeeAlso()));
         } catch (AtlasBaseException e) {
             fail("Term anchor change should've succeeded", e);
         }
@@ -426,9 +453,11 @@ public class GlossaryServiceTest {
         }
 
         customerCategory.setAnchor(newGlossaryHeader);
+        customerCategory.setChildrenCategories(null);
 
         try {
-            glossaryService.updateCategory(customerCategory);
+            customerCategory = 
glossaryService.updateCategory(customerCategory);
+            
assertTrue(CollectionUtils.isEmpty(customerCategory.getChildrenCategories()));
         } catch (AtlasBaseException e) {
             fail("Category anchor change should've succeeded");
         }
@@ -447,6 +476,7 @@ public class GlossaryServiceTest {
         assertNotNull(accountCategory);
         try {
             accountCategory = 
glossaryService.getCategory(accountCategory.getGuid());
+            assertTrue(CollectionUtils.isEmpty(accountCategory.getTerms()));
         } catch (AtlasBaseException e) {
             fail("Fetch of accountCategory should've succeeded", e);
         }
@@ -515,24 +545,17 @@ public class GlossaryServiceTest {
         assertNotNull(customerCategory);
         try {
             customerCategory = 
glossaryService.getCategory(customerCategory.getGuid());
+            assertNull(customerCategory.getParentCategory());
+            assertNotNull(customerCategory.getChildrenCategories());
+            assertEquals(customerCategory.getChildrenCategories().size(), 1); 
// Only account category
         } catch (AtlasBaseException e) {
             fail("Fetch of accountCategory should've succeeded", e);
         }
-        List<AtlasGlossaryCategory> categories = new ArrayList<>();
-        for (AtlasGlossaryCategory category : Arrays.asList(accountCategory, 
mortgageCategory)) {
-            try {
-                
categories.add(glossaryService.getCategory(category.getGuid()));
-            } catch (AtlasBaseException e) {
-                fail("Category fetch should've succeeded");
-            }
-        }
 
-        for (AtlasGlossaryCategory category : categories) {
-            AtlasRelatedCategoryHeader id = new AtlasRelatedCategoryHeader();
-            id.setCategoryGuid(category.getGuid());
-            id.setDescription("Sub-category of customer");
-            customerCategory.addChild(id);
-        }
+        AtlasRelatedCategoryHeader id = new AtlasRelatedCategoryHeader();
+        id.setCategoryGuid(mortgageCategory.getGuid());
+        id.setDescription("Sub-category of customer");
+        customerCategory.addChild(id);
 
         try {
             AtlasGlossaryCategory updateGlossaryCategory = 
glossaryService.updateCategory(customerCategory);
@@ -544,7 +567,7 @@ public class GlossaryServiceTest {
             fail("Sub category addition should've succeeded", e);
         }
 
-        for (AtlasGlossaryCategory childCategory : categories) {
+        for (AtlasGlossaryCategory childCategory : 
Arrays.asList(accountCategory, mortgageCategory)) {
             try {
                 AtlasGlossaryCategory child = 
glossaryService.getCategory(childCategory.getGuid());
                 assertNotNull(child);

http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java 
b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
index f0c5d86..10fb403 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
@@ -214,6 +214,7 @@ public class GlossaryREST {
      * @throws AtlasBaseException
      * @HTTP 200 If glossary creation was successful
      * @HTTP 400 If Glossary definition has invalid or missing information
+     * @HTTP 409 If Glossary definition already exists (duplicate 
qualifiedName)
      */
     @POST
     public AtlasGlossary createGlossary(AtlasGlossary atlasGlossary) throws 
AtlasBaseException {
@@ -236,6 +237,7 @@ public class GlossaryREST {
      * @throws AtlasBaseException
      * @HTTP 200 If glossary term creation was successful
      * @HTTP 400 If Glossary term definition has invalid or missing information
+     * @HTTP 409 If Glossary term already exists (duplicate qualifiedName)
      */
     @POST
     @Path("/term")
@@ -289,6 +291,7 @@ public class GlossaryREST {
      * @throws AtlasBaseException
      * @HTTP 200 If glossary category creation was successful
      * @HTTP 400 If Glossary category definition has invalid or missing 
information
+     * @HTTP 409 If Glossary category already exists (duplicate qualifiedName)
      */
     @POST
     @Path("/category")

Reply via email to