ATLAS-2534: Glossary REST API implementation

Change-Id: I47210446be9e38c274bae0ee4a688187ba6e4fd0
Signed-off-by: Madhan Neethiraj <[email protected]>


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

Branch: refs/heads/master
Commit: 0dad95296daa5ee4ae38904eb211af0165503fb0
Parents: 15967a9
Author: apoorvnaik <[email protected]>
Authored: Wed Mar 14 21:03:37 2018 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Sun Apr 15 01:24:45 2018 -0700

----------------------------------------------------------------------
 .../org/apache/atlas/repository/Constants.java  |  67 ++-
 .../java/org/apache/atlas/AtlasErrorCode.java   |  11 +-
 .../atlas/model/glossary/AtlasGlossaryTerm.java |  20 +-
 .../relations/AtlasRelatedCategoryHeader.java   |  13 +-
 .../atlas/discovery/EntityDiscoveryService.java |   4 +-
 .../atlas/glossary/GlossaryCategoryUtils.java   | 391 ++++++++++++
 .../apache/atlas/glossary/GlossaryService.java  | 596 +++++--------------
 .../atlas/glossary/GlossaryTermUtils.java       | 415 +++++++++++++
 .../apache/atlas/glossary/GlossaryUtils.java    |  86 +++
 .../apache/atlas/repository/ogm/DataAccess.java |   8 +-
 .../ogm/glossary/AtlasGlossaryTermDTO.java      |   8 +-
 .../graph/v1/AtlasRelationshipStoreV1.java      |   1 +
 .../store/graph/v1/EntityGraphRetriever.java    | 119 +++-
 .../atlas/glossary/GlossaryServiceTest.java     | 396 +++++++-----
 .../org/apache/atlas/web/rest/GlossaryREST.java |  22 +-
 15 files changed, 1467 insertions(+), 690 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/common/src/main/java/org/apache/atlas/repository/Constants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java 
b/common/src/main/java/org/apache/atlas/repository/Constants.java
index 7ccc748..0cef5f2 100644
--- a/common/src/main/java/org/apache/atlas/repository/Constants.java
+++ b/common/src/main/java/org/apache/atlas/repository/Constants.java
@@ -6,9 +6,9 @@
  * 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
- *
+ * <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.
@@ -28,10 +28,10 @@ public final class Constants {
      * Globally Unique identifier property key.
      */
 
-    public static final String INTERNAL_PROPERTY_KEY_PREFIX = "__";
+    public static final String INTERNAL_PROPERTY_KEY_PREFIX     = "__";
     public static final String RELATIONSHIP_PROPERTY_KEY_PREFIX = "_r";
-    public static final String GUID_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "guid";
-    public static final String RELATIONSHIP_GUID_PROPERTY_KEY = 
RELATIONSHIP_PROPERTY_KEY_PREFIX + GUID_PROPERTY_KEY;
+    public static final String GUID_PROPERTY_KEY                = 
INTERNAL_PROPERTY_KEY_PREFIX + "guid";
+    public static final String RELATIONSHIP_GUID_PROPERTY_KEY   = 
RELATIONSHIP_PROPERTY_KEY_PREFIX + GUID_PROPERTY_KEY;
 
     /**
      * Entity type name property key.
@@ -53,35 +53,35 @@ public final class Constants {
     /**
      * Properties for type store graph.
      */
-    public static final String TYPE_CATEGORY_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.category";
-    public static final String VERTEX_TYPE_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type";
-    public static final String TYPENAME_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.name";
+    public static final String TYPE_CATEGORY_PROPERTY_KEY   = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.category";
+    public static final String VERTEX_TYPE_PROPERTY_KEY     = 
INTERNAL_PROPERTY_KEY_PREFIX + "type";
+    public static final String TYPENAME_PROPERTY_KEY        = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.name";
     public static final String TYPEDESCRIPTION_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.description";
-    public static final String TYPEVERSION_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.version";
-    public static final String TYPEOPTIONS_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.options";
+    public static final String TYPEVERSION_PROPERTY_KEY     = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.version";
+    public static final String TYPEOPTIONS_PROPERTY_KEY     = 
INTERNAL_PROPERTY_KEY_PREFIX + "type.options";
 
     // relationship def constants
-    public static final String RELATIONSHIPTYPE_END1_KEY = "endDef1";
-    public static final String RELATIONSHIPTYPE_END2_KEY = "endDef2";
-    public static final String RELATIONSHIPTYPE_CATEGORY_KEY = 
"relationshipCategory";
-    public static final String RELATIONSHIPTYPE_TAG_PROPAGATION_KEY = 
"tagPropagation";
+    public static final String RELATIONSHIPTYPE_END1_KEY                       
        = "endDef1";
+    public static final String RELATIONSHIPTYPE_END2_KEY                       
        = "endDef2";
+    public static final String RELATIONSHIPTYPE_CATEGORY_KEY                   
        = "relationshipCategory";
+    public static final String RELATIONSHIPTYPE_TAG_PROPAGATION_KEY            
        = "tagPropagation";
     public static final String 
RELATIONSHIPTYPE_BLOCKED_PROPAGATED_CLASSIFICATIONS_KEY = 
"blockedPropagatedClassifications";
 
     /**
      * Trait names property key and index name.
      */
-    public static final String TRAIT_NAMES_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "traitNames";
+    public static final String TRAIT_NAMES_PROPERTY_KEY            = 
INTERNAL_PROPERTY_KEY_PREFIX + "traitNames";
     public static final String PROPAGATED_TRAIT_NAMES_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "propagatedTraitNames";
 
     public static final String VERSION_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "version";
-    public static final String STATE_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "state";
-    public static final String CREATED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + 
"createdBy";
-    public static final String MODIFIED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX 
+ "modifiedBy";
+    public static final String STATE_PROPERTY_KEY   = 
INTERNAL_PROPERTY_KEY_PREFIX + "state";
+    public static final String CREATED_BY_KEY       = 
INTERNAL_PROPERTY_KEY_PREFIX + "createdBy";
+    public static final String MODIFIED_BY_KEY      = 
INTERNAL_PROPERTY_KEY_PREFIX + "modifiedBy";
 
     public static final String TIMESTAMP_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "timestamp";
 
     public static final String MODIFICATION_TIMESTAMP_PROPERTY_KEY =
-        INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp";
+            INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp";
 
     /**
      * search backing index name.
@@ -100,23 +100,23 @@ public final class Constants {
 
     public static final String FULLTEXT_INDEX = "fulltext_index";
 
-    public static final String QUALIFIED_NAME = "Referenceable.qualifiedName";
-    public static final String TYPE_NAME_PROPERTY_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "typeName";
-    public static final String INDEX_SEARCH_MAX_RESULT_SET_SIZE = 
"atlas.graph.index.search.max-result-set-size";
+    public static final String QUALIFIED_NAME                          = 
"Referenceable.qualifiedName";
+    public static final String TYPE_NAME_PROPERTY_KEY                  = 
INTERNAL_PROPERTY_KEY_PREFIX + "typeName";
+    public static final String INDEX_SEARCH_MAX_RESULT_SET_SIZE        = 
"atlas.graph.index.search.max-result-set-size";
     public static final String INDEX_SEARCH_TYPES_MAX_QUERY_STR_LENGTH = 
"atlas.graph.index.search.types.max-query-str-length";
     public static final String INDEX_SEARCH_TAGS_MAX_QUERY_STR_LENGTH  = 
"atlas.graph.index.search.tags.max-query-str-length";
-    public static final String INDEX_SEARCH_VERTEX_PREFIX_PROPERTY  = 
"atlas.graph.index.search.vertex.prefix";
-    public static final String INDEX_SEARCH_VERTEX_PREFIX_DEFAULT = "$v$";
+    public static final String INDEX_SEARCH_VERTEX_PREFIX_PROPERTY     = 
"atlas.graph.index.search.vertex.prefix";
+    public static final String INDEX_SEARCH_VERTEX_PREFIX_DEFAULT      = "$v$";
 
-    public static final String MAX_FULLTEXT_QUERY_STR_LENGTH  = 
"atlas.graph.fulltext-max-query-str-length";
-    public static final String MAX_DSL_QUERY_STR_LENGTH  = 
"atlas.graph.dsl-max-query-str-length";
+    public static final String MAX_FULLTEXT_QUERY_STR_LENGTH = 
"atlas.graph.fulltext-max-query-str-length";
+    public static final String MAX_DSL_QUERY_STR_LENGTH      = 
"atlas.graph.dsl-max-query-str-length";
 
-    public static final String ATTRIBUTE_NAME_GUID     = "guid";
-    public static final String ATTRIBUTE_NAME_TYPENAME = "typeName";
+    public static final String ATTRIBUTE_NAME_GUID           = "guid";
+    public static final String ATTRIBUTE_NAME_TYPENAME       = "typeName";
     public static final String ATTRIBUTE_NAME_SUPERTYPENAMES = 
"superTypeNames";
-    public static final String ATTRIBUTE_NAME_STATE    = "state";
-    public static final String ATTRIBUTE_NAME_VERSION  = "version";
-    public static final String TEMP_STRUCT_NAME_PREFIX = 
"__tempQueryResultStruct";
+    public static final String ATTRIBUTE_NAME_STATE          = "state";
+    public static final String ATTRIBUTE_NAME_VERSION        = "version";
+    public static final String TEMP_STRUCT_NAME_PREFIX       = 
"__tempQueryResultStruct";
 
     public static final String CLASSIFICATION_ENTITY_GUID                     
= INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid";
     public static final String CLASSIFICATION_VALIDITY_PERIODS_KEY            
= INTERNAL_PROPERTY_KEY_PREFIX + "validityPeriods";
@@ -126,9 +126,10 @@ public final class Constants {
     public static final String CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY 
= INTERNAL_PROPERTY_KEY_PREFIX + "isPropagated";
     public static final String CLASSIFICATION_EDGE_STATE_PROPERTY_KEY         
= STATE_PROPERTY_KEY;
     public static final String CLASSIFICATION_LABEL                           
= "classifiedAs";
+    public static final String TERM_ASSIGNMENT_LABEL                          
= "r:__AtlasGlossarySemanticAssignment";
 
     public static final String VERTEX_ID_IN_IMPORT_KEY = "__vIdInImport";
-    public static final String EDGE_ID_IN_IMPORT_KEY = "__eIdInImport";
+    public static final String EDGE_ID_IN_IMPORT_KEY   = "__eIdInImport";
 
     private Constants() {
     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 c6be362..539a225 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -128,9 +128,16 @@ public enum AtlasErrorCode {
     NO_CLASSIFICATIONS_FOUND_FOR_ENTITY(400, "ATLAS-400-00-06E", "No 
classifications associated with entity: {0}"),
     INVALID_CLASSIFICATION_PARAMS(400, "ATLAS-400-00-06F", "Invalid 
classification parameters passed for {0} operation for entity: {1}"),
     PROPAGATED_CLASSIFICATION_NOT_ASSOCIATED_WITH_ENTITY(400, 
"ATLAS-400-00-070", "Propagated classification {0} is not associated with 
entity"),
-    INVALID_PARTIAL_UPDATE_ATTR_VAL(400, "ATLAS-400-00-071", "Invalid attrVal 
for partial update of {0}, expected = {1} found {2}"),
+    INVALID_BLOCKED_PROPAGATED_CLASSIFICATION(400, "ATLAS-400-00-071", 
"Invalid propagated classification: {0} with entityGuid: {1} added to blocked 
propagated classifications."),
     MISSING_MANDATORY_ANCHOR(400, "ATLAS-400-00-072", "Mandatory anchor 
attribute is missing"),
-    INVALID_BLOCKED_PROPAGATED_CLASSIFICATION(400, "ATLAS-400-00-073", 
"Invalid propagated classification: {0} with entityGuid: {1} added to blocked 
propagated classifications."),
+    MISSING_MANDATORY_QUALIFIED_NAME(400, "ATLAS-400-00-073", "Mandatory 
qualifiedName attribute is missing"),
+    INVALID_PARTIAL_UPDATE_ATTR_VAL(400, "ATLAS-400-00-074", "Invalid attrVal 
for partial update of {0}, expected = {1} found {2}"),
+    MISSING_TERM_ID_FOR_CATEGORIZATION(400, "ATLAS-400-00-075", "Term guid 
can't be empty/null when adding to a category"),
+    INVALID_NEW_ANCHOR_GUID(400, "ATLAS-400-00-076", "New Anchor guid can't be 
empty/null"),
+    TERM_DISSOCIATION_MISSING_RELATION_GUID(400, "ATLAS-400-00-077", "Missing 
mandatory attribute, TermAssignment relationship guid"),
+    GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-078", 
"Attributes qualifiedName and displayName are missing. Failed to derive a 
unique name for Glossary"),
+    GLOSSARY_TERM_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-079", 
"Attributes qualifiedName, displayName & glossary name are missing. Failed to 
derive a unique name for Glossary term"),
+    GLOSSARY_CATEGORY_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-07A", 
"Attributes qualifiedName, displayName & glossary name are missing. Failed to 
derive a unique name for Glossary category"),
 
     UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to 
perform {1}"),
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryTerm.java
----------------------------------------------------------------------
diff --git 
a/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryTerm.java 
b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryTerm.java
index f42bf35..3d714a8 100644
--- a/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryTerm.java
+++ b/intg/src/main/java/org/apache/atlas/model/glossary/AtlasGlossaryTerm.java
@@ -23,7 +23,7 @@ import org.apache.atlas.model.annotation.AtlasJSON;
 import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader;
 import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
 import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
-import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasRelatedObjectId;
 import org.apache.commons.collections.CollectionUtils;
 
 import java.util.HashMap;
@@ -42,7 +42,7 @@ public class AtlasGlossaryTerm extends 
AtlasGlossaryBaseObject {
 
     // Attributes derived from relationships
     private AtlasGlossaryHeader                anchor;
-    private Set<AtlasEntityHeader>             assignedEntities;
+    private Set<AtlasRelatedObjectId>          assignedEntities;
     private Set<AtlasTermCategorizationHeader> categories;
 
     // Related Terms
@@ -128,21 +128,21 @@ public class AtlasGlossaryTerm extends 
AtlasGlossaryBaseObject {
         setCategories(categories);
     }
 
-    public Set<AtlasEntityHeader> getAssignedEntities() {
+    public Set<AtlasRelatedObjectId> getAssignedEntities() {
         return assignedEntities;
     }
 
-    public void setAssignedEntities(final Set<AtlasEntityHeader> 
assignedEntities) {
+    public void setAssignedEntities(final Set<AtlasRelatedObjectId> 
assignedEntities) {
         this.assignedEntities = assignedEntities;
     }
 
-    public void addAssignedEntity(final AtlasEntityHeader entityHeader) {
-        Set<AtlasEntityHeader> entityHeaders = this.assignedEntities;
-        if (entityHeaders == null) {
-            entityHeaders = new HashSet<>();
+    public void addAssignedEntity(final AtlasRelatedObjectId atlasObjectId) {
+        Set<AtlasRelatedObjectId> assignedEntities = this.assignedEntities;
+        if (assignedEntities == null) {
+            assignedEntities = new HashSet<>();
         }
-        entityHeaders.add(entityHeader);
-        setAssignedEntities(entityHeaders);
+        assignedEntities.add(atlasObjectId);
+        setAssignedEntities(assignedEntities);
     }
 
     public Set<AtlasRelatedTermHeader> getSeeAlso() {

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/intg/src/main/java/org/apache/atlas/model/glossary/relations/AtlasRelatedCategoryHeader.java
----------------------------------------------------------------------
diff --git 
a/intg/src/main/java/org/apache/atlas/model/glossary/relations/AtlasRelatedCategoryHeader.java
 
b/intg/src/main/java/org/apache/atlas/model/glossary/relations/AtlasRelatedCategoryHeader.java
index aa7a6b1..a62493e 100644
--- 
a/intg/src/main/java/org/apache/atlas/model/glossary/relations/AtlasRelatedCategoryHeader.java
+++ 
b/intg/src/main/java/org/apache/atlas/model/glossary/relations/AtlasRelatedCategoryHeader.java
@@ -24,6 +24,7 @@ import java.util.Objects;
 @AtlasJSON
 public class AtlasRelatedCategoryHeader {
     private String categoryGuid;
+    private String parentCategoryGuid;
     private String relationGuid;
     private String displayText;
     private String description;
@@ -61,6 +62,7 @@ public class AtlasRelatedCategoryHeader {
         if (!(o instanceof AtlasRelatedCategoryHeader)) return false;
         final AtlasRelatedCategoryHeader that = (AtlasRelatedCategoryHeader) o;
         return Objects.equals(categoryGuid, that.categoryGuid) &&
+                       Objects.equals(parentCategoryGuid, 
that.parentCategoryGuid) &&
                        Objects.equals(displayText, that.displayText) &&
                        Objects.equals(description, that.description);
     }
@@ -68,13 +70,14 @@ public class AtlasRelatedCategoryHeader {
     @Override
     public int hashCode() {
 
-        return Objects.hash(categoryGuid, displayText, description);
+        return Objects.hash(categoryGuid, parentCategoryGuid, displayText, 
description);
     }
 
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder("AtlasRelatedCategoryId{");
         sb.append("categoryGuid='").append(categoryGuid).append('\'');
+        sb.append(", 
parentCategoryGuid='").append(parentCategoryGuid).append('\'');
         sb.append(", relationGuid='").append(relationGuid).append('\'');
         sb.append(", displayText='").append(displayText).append('\'');
         sb.append(", description='").append(description).append('\'');
@@ -90,4 +93,12 @@ public class AtlasRelatedCategoryHeader {
     public void setRelationGuid(final String relationGuid) {
         this.relationGuid = relationGuid;
     }
+
+    public String getParentCategoryGuid() {
+        return parentCategoryGuid;
+    }
+
+    public void setParentCategoryGuid(final String parentCategoryGuid) {
+        this.parentCategoryGuid = parentCategoryGuid;
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
index 36fb0bc..411d9b4 100644
--- 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -475,7 +475,7 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
                         AtlasObjectId objId = (AtlasObjectId) attrValue;
 
                         if (ret.getReferredEntities() == null) {
-                            ret.setReferredEntities(new HashMap<String, 
AtlasEntityHeader>());
+                            ret.setReferredEntities(new HashMap<>());
                         }
 
                         if 
(!ret.getReferredEntities().containsKey(objId.getGuid())) {
@@ -489,7 +489,7 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
                                 AtlasObjectId objId = (AtlasObjectId) obj;
 
                                 if (ret.getReferredEntities() == null) {
-                                    ret.setReferredEntities(new 
HashMap<String, AtlasEntityHeader>());
+                                    ret.setReferredEntities(new HashMap<>());
                                 }
 
                                 if 
(!ret.getReferredEntities().containsKey(objId.getGuid())) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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
new file mode 100644
index 0000000..46d8889
--- /dev/null
+++ 
b/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java
@@ -0,0 +1,391 @@
+/**
+ * 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.glossary;
+
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasRelationship;
+import org.apache.atlas.model.instance.AtlasStruct;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class GlossaryCategoryUtils extends GlossaryUtils {
+    private static final Logger  LOG           = 
LoggerFactory.getLogger(GlossaryCategoryUtils.class);
+    private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
+
+    protected GlossaryCategoryUtils(AtlasRelationshipStore relationshipStore, 
AtlasTypeRegistry typeRegistry) {
+        super(relationshipStore, typeRegistry);
+    }
+
+    public void processCategoryRelations(AtlasGlossaryCategory 
updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) 
throws AtlasBaseException {
+        if (DEBUG_ENABLED) {
+            LOG.debug("==> GlossaryCategoryUtils.processCategoryRelations({}, 
{}, {})", updatedCategory, existing, op);
+        }
+        processCategoryAnchor(updatedCategory, existing, op);
+        processParentCategory(updatedCategory, existing, op);
+        processCategoryChildren(updatedCategory, existing, op);
+        processAssociatedTerms(updatedCategory, existing, op);
+
+        if (DEBUG_ENABLED) {
+            LOG.debug("<== GlossaryCategoryUtils.processCategoryRelations()");
+        }
+    }
+
+    private void processCategoryAnchor(AtlasGlossaryCategory updatedCategory, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        if (Objects.isNull(updatedCategory.getAnchor()) && op != 
RelationshipOperation.DELETE) {
+            throw new 
AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
+        }
+
+        switch (op) {
+            case CREATE:
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Creating new category anchor, category = {}, 
glossary = {}", existing.getGuid(), 
updatedCategory.getAnchor().getDisplayText());
+                }
+                String anchorGlossaryGuid = 
updatedCategory.getAnchor().getGlossaryGuid();
+                
createRelationship(defineCategoryAnchorRelation(anchorGlossaryGuid, 
existing.getGuid()));
+                break;
+            case UPDATE:
+                if (!Objects.equals(updatedCategory.getAnchor(), 
existing.getAnchor())) {
+                    if 
(Objects.isNull(updatedCategory.getAnchor().getGlossaryGuid())) {
+                        throw new 
AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID);
+                    }
+
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Updating category anchor, category = {}, 
currAnchor = {}, newAnchor = {}", existing.getGuid(),
+                                  existing.getAnchor().getDisplayText(), 
updatedCategory.getAnchor().getDisplayText());
+                    }
+                    
relationshipStore.deleteById(existing.getAnchor().getRelationGuid());
+                    
createRelationship(defineCategoryAnchorRelation(updatedCategory.getAnchor().getGlossaryGuid(),
 existing.getGuid()));
+                }
+                break;
+            case DELETE:
+                if (Objects.nonNull(existing.getAnchor())) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Deleting category anchor");
+                    }
+                    
relationshipStore.deleteById(existing.getAnchor().getRelationGuid());
+                }
+                break;
+        }
+    }
+
+    private void processParentCategory(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        AtlasRelatedCategoryHeader newParent      = newObj.getParentCategory();
+        AtlasRelatedCategoryHeader existingParent = 
existing.getParentCategory();
+        switch (op) {
+            case CREATE:
+                if (Objects.nonNull(newParent)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Creating new parent, category = {}, parent 
= {}", existing.getGuid(), newParent.getDisplayText());
+                    }
+                    createRelationship(defineCategoryHierarchyLink(newParent, 
existing.getGuid()));
+                }
+                break;
+            case UPDATE:
+                if (Objects.equals(newParent, existingParent)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("No change to parent");
+                    }
+                    break;
+                }
+
+                if (Objects.isNull(existingParent)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Creating new parent, category = {}, parent 
= {}", existing.getGuid(), newParent.getDisplayText());
+                    }
+                    createRelationship(defineCategoryHierarchyLink(newParent, 
existing.getGuid()));
+                } else if (Objects.isNull(newParent)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Removing category parent, category = {}, 
parent = {}", existing.getGuid(), existingParent.getDisplayText());
+                    }
+                    
relationshipStore.deleteById(existingParent.getRelationGuid());
+                } else {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Updating category parent, category = {}, 
currParent = {}, newParent = {}", existing.getGuid(), 
existingParent.getDisplayText(), newParent.getDisplayText());
+                    }
+                    AtlasRelationship parentRelationship = 
relationshipStore.getById(existingParent.getRelationGuid());
+                    if 
(existingParent.getCategoryGuid().equals(newParent.getCategoryGuid())) {
+                        updateRelationshipAttributes(parentRelationship, 
newParent);
+                        relationshipStore.update(parentRelationship);
+                    } else {
+                        // Delete link to existing parent and link to new 
parent
+                        
relationshipStore.deleteById(parentRelationship.getGuid());
+                        
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
+                    }
+                }
+                break;
+            case DELETE:
+                if (Objects.nonNull(existingParent)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Removing category parent, category = {}, 
parent = {}", existing.getGuid(), existingParent.getDisplayText());
+                    }
+                    
relationshipStore.deleteById(existingParent.getRelationGuid());
+                }
+                break;
+        }
+    }
+
+    private void processAssociatedTerms(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        Set<AtlasRelatedTermHeader> newTerms      = newObj.getTerms();
+        Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
+
+        switch (op) {
+            case CREATE:
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Creating term relation with category = {}, 
terms = {}", existing.getDisplayName(),
+                              Objects.nonNull(newTerms) ? newTerms.size() : 
"none");
+                }
+                createTermCategorizationRelationships(existing, newTerms);
+                break;
+            case UPDATE:
+                if (CollectionUtils.isEmpty(existingTerms)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Creating term relation with category = {}, 
terms = {}", existing.getDisplayName(),
+                                  Objects.nonNull(newTerms) ? newTerms.size() 
: "none");
+                    }
+                    createTermCategorizationRelationships(existing, newTerms);
+                    break;
+                }
+
+                if (CollectionUtils.isEmpty(newTerms)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Deleting term relation with category = {}, 
terms = {}", existing.getDisplayName(), existingTerms.size());
+                    }
+                    deleteTermCategorizationRelationships(existing, 
existingTerms);
+                    break;
+                }
+
+                Set<AtlasRelatedTermHeader> toCreate = newTerms
+                                                               .stream()
+                                                               .filter(c -> 
Objects.isNull(c.getRelationGuid()))
+                                                               
.collect(Collectors.toSet());
+                createTermCategorizationRelationships(existing, toCreate);
+
+                Set<AtlasRelatedTermHeader> toUpdate = newTerms
+                                                               .stream()
+                                                               .filter(c -> 
Objects.nonNull(c.getRelationGuid()) && existingTerms.contains(c))
+                                                               
.collect(Collectors.toSet());
+                updateTermCategorizationRelationships(existing, toUpdate);
+
+                Set<AtlasRelatedTermHeader> toDelete = existingTerms
+                                                               .stream()
+                                                               .filter(c -> 
!toCreate.contains(c) && !toUpdate.contains(c))
+                                                               
.collect(Collectors.toSet());
+                deleteTermCategorizationRelationships(existing, toDelete);
+                break;
+            case DELETE:
+                deleteTermCategorizationRelationships(existing, existingTerms);
+                break;
+        }
+    }
+
+    private void createTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(terms)) {
+            Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
+            for (AtlasRelatedTermHeader term : terms) {
+                if (Objects.isNull(term.getTermGuid())) {
+                    throw new 
AtlasBaseException(AtlasErrorCode.MISSING_TERM_ID_FOR_CATEGORIZATION);
+                } else {
+                    if (Objects.nonNull(existingTerms) && 
existingTerms.contains(term)) {
+                        if (DEBUG_ENABLED) {
+                            LOG.debug("Skipping existing term guid={}", 
term.getTermGuid());
+                        }
+                        continue;
+                    }
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Creating relation between category = {} and 
term = {}", existing.getGuid(), term.getDisplayText());
+                    }
+                    
createRelationship(defineCategorizedTerm(existing.getGuid(), term));
+                }
+            }
+        }
+    }
+
+    private void updateTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(terms)) {
+            for (AtlasRelatedTermHeader term : terms) {
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Updating term relation with category = {}, term 
= {}", existing.getDisplayName(), term.getDisplayText());
+                }
+                AtlasRelationship relationship = 
relationshipStore.getById(term.getRelationGuid());
+                updateRelationshipAttributes(relationship, term);
+                relationshipStore.update(relationship);
+            }
+        }
+    }
+
+    private void deleteTermCategorizationRelationships(AtlasGlossaryCategory 
existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(terms)) {
+            for (AtlasRelatedTermHeader term : terms) {
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Creating term relation with category = {}, 
terms = {}", existing.getDisplayName(), term.getDisplayText());
+                }
+                relationshipStore.deleteById(term.getRelationGuid());
+            }
+        }
+    }
+
+    private void processCategoryChildren(AtlasGlossaryCategory newObj, 
AtlasGlossaryCategory existing, RelationshipOperation op) throws 
AtlasBaseException {
+        Set<AtlasRelatedCategoryHeader> newChildren      = 
newObj.getChildrenCategories();
+        Set<AtlasRelatedCategoryHeader> existingChildren = 
existing.getChildrenCategories();
+        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);
+                break;
+            case UPDATE:
+                // Create new children
+                if (CollectionUtils.isEmpty(existingChildren)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Creating new children, category = {}, 
children = {}", existing.getDisplayName(),
+                                  Objects.nonNull(newChildren) ? 
newChildren.size() : "none");
+                    }
+                    createCategoryRelationships(existing, newChildren);
+                    break;
+                }
+                // Delete current children
+                if (CollectionUtils.isEmpty(newChildren)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Deleting children, category = {}, children 
= {}", existing.getDisplayName(), existingChildren.size());
+                    }
+                    deleteCategoryRelationships(existing, existingChildren);
+                    break;
+                }
+
+                Set<AtlasRelatedCategoryHeader> toCreate = newChildren
+                                                                   .stream()
+                                                                   .filter(c 
-> Objects.isNull(c.getRelationGuid()))
+                                                                   
.collect(Collectors.toSet());
+                createCategoryRelationships(existing, toCreate);
+
+                Set<AtlasRelatedCategoryHeader> toUpdate = newChildren
+                                                                   .stream()
+                                                                   .filter(c 
-> Objects.nonNull(c.getRelationGuid()) && existingChildren.contains(c))
+                                                                   
.collect(Collectors.toSet());
+                updateCategoryRelationships(existing, toUpdate);
+
+                Set<AtlasRelatedCategoryHeader> toDelete = existingChildren
+                                                                   .stream()
+                                                                   .filter(c 
-> !toCreate.contains(c) && !toUpdate.contains(c))
+                                                                   
.collect(Collectors.toSet());
+                deleteCategoryRelationships(existing, toDelete);
+                break;
+            case DELETE:
+                deleteCategoryRelationships(existing, existingChildren);
+                break;
+        }
+    }
+
+    private void createCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(newChildren)) {
+            Set<AtlasRelatedCategoryHeader> existingChildren = 
existing.getChildrenCategories();
+            for (AtlasRelatedCategoryHeader child : newChildren) {
+                if (Objects.nonNull(existingChildren) && 
existingChildren.contains(child)) {
+                    if (DEBUG_ENABLED) {
+                        LOG.debug("Skipping existing child relation for 
category guid = {}", child.getCategoryGuid());
+                    }
+                    continue;
+                }
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Creating new child, category = {}, child = {}", 
existing.getDisplayName(), child.getDisplayText());
+                }
+                
createRelationship(defineCategoryHierarchyLink(existing.getGuid(), child));
+            }
+        }
+    }
+
+    private void updateCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(toUpdate)) {
+            for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) {
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Updating child, category = {}, child = {}", 
existing.getDisplayName(), categoryHeader.getDisplayText());
+                }
+                AtlasRelationship childRelationship = 
relationshipStore.getById(categoryHeader.getRelationGuid());
+                updateRelationshipAttributes(childRelationship, 
categoryHeader);
+                relationshipStore.update(childRelationship);
+            }
+        }
+    }
+
+    private void deleteCategoryRelationships(AtlasGlossaryCategory existing, 
Set<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(existingChildren)) {
+            for (AtlasRelatedCategoryHeader child : existingChildren) {
+                if (DEBUG_ENABLED) {
+                    LOG.debug("Deleting child, category = {}, child = {}", 
existing.getDisplayName(), child.getDisplayText());
+                }
+                relationshipStore.deleteById(child.getRelationGuid());
+            }
+        }
+    }
+
+    private AtlasRelationship defineCategoryAnchorRelation(String 
glossaryGuid, String categoryGuid) {
+        AtlasRelationshipType relationshipType = 
typeRegistry.getRelationshipTypeByName(CATEGORY_ANCHOR);
+        AtlasStruct           defaultAttrs     = 
relationshipType.createDefaultValue();
+
+        return new AtlasRelationship(CATEGORY_ANCHOR, new 
AtlasObjectId(glossaryGuid), new AtlasObjectId(categoryGuid), 
defaultAttrs.getAttributes());
+    }
+
+    private AtlasRelationship defineCategoryHierarchyLink(String 
parentCategoryGuid, AtlasRelatedCategoryHeader childCategory) {
+        AtlasRelationshipType relationshipType = 
typeRegistry.getRelationshipTypeByName(CATEGORY_HIERARCHY);
+        AtlasStruct           defaultAttrs     = 
relationshipType.createDefaultValue();
+
+        AtlasRelationship relationship = new 
AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategoryGuid), 
new AtlasObjectId(childCategory.getCategoryGuid()), 
defaultAttrs.getAttributes());
+        updateRelationshipAttributes(relationship, childCategory);
+        return relationship;
+    }
+
+    private AtlasRelationship 
defineCategoryHierarchyLink(AtlasRelatedCategoryHeader parentCategory, String 
childGuid) {
+        AtlasRelationshipType relationshipType = 
typeRegistry.getRelationshipTypeByName(CATEGORY_HIERARCHY);
+        AtlasStruct           defaultAttrs     = 
relationshipType.createDefaultValue();
+
+        AtlasRelationship relationship = new 
AtlasRelationship(CATEGORY_HIERARCHY, new 
AtlasObjectId(parentCategory.getCategoryGuid()), new AtlasObjectId(childGuid), 
defaultAttrs.getAttributes());
+        updateRelationshipAttributes(relationship, parentCategory);
+        return relationship;
+    }
+
+    private AtlasRelationship defineCategorizedTerm(String categoryGuid, 
AtlasRelatedTermHeader relatedTermId) {
+        AtlasRelationshipType relationshipType = 
typeRegistry.getRelationshipTypeByName(TERM_CATEGORIZATION);
+        AtlasStruct           defaultAttrs     = 
relationshipType.createDefaultValue();
+
+        AtlasRelationship relationship = new 
AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(categoryGuid), new 
AtlasObjectId(relatedTermId.getTermGuid()), defaultAttrs.getAttributes());
+        updateRelationshipAttributes(relationship, relatedTermId);
+        return relationship;
+    }
+
+    private void updateRelationshipAttributes(AtlasRelationship relationship, 
AtlasRelatedCategoryHeader relatedCategoryHeader) {
+        if (Objects.nonNull(relationship)) {
+            relationship.setAttribute("description", 
relatedCategoryHeader.getDescription());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 49c8f51..9fd795b 100644
--- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
@@ -26,13 +26,13 @@ import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
 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.AtlasEntityHeader;
-import org.apache.atlas.model.instance.AtlasObjectId;
-import org.apache.atlas.model.instance.AtlasRelationship;
+import org.apache.atlas.model.instance.AtlasRelatedObjectId;
 import org.apache.atlas.repository.ogm.DataAccess;
 import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
+import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -53,24 +53,17 @@ public class GlossaryService {
     private static final Logger  LOG           = 
LoggerFactory.getLogger(GlossaryService.class);
     private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
 
-    private static final String ATLAS_GLOSSARY_PREFIX = "__AtlasGlossary";
-    // Relation name constants
-    private static final String TERM_ANCHOR           = ATLAS_GLOSSARY_PREFIX 
+ "TermAnchor";
-    private static final String CATEGORY_ANCHOR       = ATLAS_GLOSSARY_PREFIX 
+ "CategoryAnchor";
-    private static final String CATEGORY_HIERARCHY    = ATLAS_GLOSSARY_PREFIX 
+ "CategoryHierarchyLink";
-    private static final String TERM_CATEGORIZATION   = ATLAS_GLOSSARY_PREFIX 
+ "TermCategorization";
-    private static final String TERM_ASSIGNMENT       = ATLAS_GLOSSARY_PREFIX 
+ "SemanticAssignment";
-
     private final DataAccess             dataAccess;
-    private final AtlasRelationshipStore relationshipStore;
+    private final GlossaryTermUtils      glossaryTermUtils;
+    private final GlossaryCategoryUtils  glossaryCategoryUtils;
 
     @Inject
-    public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore 
relationshipStore) {
+    public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore 
relationshipStore, final AtlasTypeRegistry typeRegistry) {
         this.dataAccess = dataAccess;
-        this.relationshipStore = relationshipStore;
+        glossaryTermUtils = new GlossaryTermUtils(relationshipStore, 
typeRegistry);
+        glossaryCategoryUtils = new GlossaryCategoryUtils(relationshipStore, 
typeRegistry);
     }
 
-
     /**
      * List all glossaries
      *
@@ -85,7 +78,7 @@ public class GlossaryService {
             LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, 
offset, sortOrder);
         }
 
-        List<String>     glossaryGuids    = 
AtlasGraphUtilsV1.findEntityGUIDsByType(ATLAS_GLOSSARY_PREFIX, sortOrder);
+        List<String>     glossaryGuids    = 
AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_PREFIX, 
sortOrder);
         PaginationHelper paginationHelper = new 
PaginationHelper<>(glossaryGuids, offset, limit);
 
         List<AtlasGlossary> ret;
@@ -95,7 +88,11 @@ public class GlossaryService {
             Iterable<AtlasGlossary> glossaries = dataAccess.load(ret);
             ret.clear();
 
-            glossaries.forEach(ret::add);
+            // Set the displayText for all relations
+            for (AtlasGlossary glossary : glossaries) {
+                setInfoForRelations(glossary);
+                ret.add(glossary);
+            }
         } else {
             ret = Collections.emptyList();
         }
@@ -121,9 +118,12 @@ public class GlossaryService {
         if (Objects.isNull(atlasGlossary)) {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary 
definition missing");
         }
-        if (Objects.isNull(atlasGlossary.getQualifiedName())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary 
qualifiedName is mandatory");
-
+        if (StringUtils.isEmpty(atlasGlossary.getQualifiedName())) {
+            if (StringUtils.isEmpty(atlasGlossary.getDisplayName())) {
+                throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED);
+            } else {
+                atlasGlossary.setQualifiedName(atlasGlossary.getDisplayName());
+            }
         }
         AtlasGlossary saved = dataAccess.save(atlasGlossary);
 
@@ -152,7 +152,7 @@ public class GlossaryService {
         AtlasGlossary atlasGlossary = getGlossarySkeleton(glossaryGuid);
         AtlasGlossary ret           = dataAccess.load(atlasGlossary);
 
-        setDisplayTextForRelations(ret);
+        setInfoForRelations(ret);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.getGlossary() : {}", ret);
@@ -219,10 +219,9 @@ public class GlossaryService {
 
         if (!ret.equals(atlasGlossary)) {
             atlasGlossary.setGuid(ret.getGuid());
-            atlasGlossary.setQualifiedName(ret.getQualifiedName());
 
             ret = dataAccess.save(atlasGlossary);
-            setDisplayTextForRelations(ret);
+            setInfoForRelations(ret);
         }
 
         if (DEBUG_ENABLED) {
@@ -239,8 +238,15 @@ public class GlossaryService {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"glossaryGuid is null/empty");
         }
 
+        AtlasGlossary existing = 
dataAccess.load(getGlossarySkeleton(glossaryGuid));
+
+        Set<AtlasRelatedTermHeader> terms = existing.getTerms();
+        deleteTerms(existing, terms);
 
-        // FIXME: When deleting all other related entities, the new edge label 
(r:<Relation>) is failing the delete calls
+        Set<AtlasRelatedCategoryHeader> categories = existing.getCategories();
+        deleteCategories(existing, categories);
+
+        // Once all relations are deleted, then delete the Glossary
         dataAccess.delete(glossaryGuid);
 
         if (DEBUG_ENABLED) {
@@ -263,7 +269,7 @@ public class GlossaryService {
         AtlasGlossaryTerm atlasGlossary = 
getAtlasGlossaryTermSkeleton(termGuid);
         AtlasGlossaryTerm ret           = dataAccess.load(atlasGlossary);
 
-        setDisplayTextForRelations(ret);
+        setInfoForRelations(ret);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.getTerm() : {}", ret);
@@ -278,24 +284,30 @@ public class GlossaryService {
         if (Objects.isNull(glossaryTerm)) {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"GlossaryTerm definition missing");
         }
-        if (Objects.isNull(glossaryTerm.getQualifiedName())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"GlossaryTerm qualifiedName is mandatory");
+        if (Objects.isNull(glossaryTerm.getAnchor())) {
+            throw new 
AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
+        }
+        if (StringUtils.isEmpty(glossaryTerm.getQualifiedName())) {
+            String displayName  = glossaryTerm.getDisplayName();
+            String glossaryName = glossaryTerm.getAnchor().getDisplayText();
+            if (StringUtils.isEmpty(displayName) || 
StringUtils.isEmpty(glossaryName)) {
+                throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_QUALIFIED_NAME_CANT_BE_DERIVED);
+            } else {
+                glossaryTerm.setQualifiedName(displayName + "@" + 
glossaryName);
+            }
         }
 
-        AtlasGlossaryTerm saved = dataAccess.save(glossaryTerm);
-
-        // TODO: Create all term relations
-        processTermAnchor(glossaryTerm, saved);
-        processRelatedTerms(glossaryTerm, saved);
-        processAssociatedCategories(glossaryTerm, saved);
+        AtlasGlossaryTerm existing = dataAccess.save(glossaryTerm);
+        glossaryTermUtils.processTermRelations(glossaryTerm, existing, 
GlossaryUtils.RelationshipOperation.CREATE);
 
-        saved = dataAccess.load(glossaryTerm);
-        setDisplayTextForRelations(saved);
+        // Re-load term after handling relations
+        existing = dataAccess.load(glossaryTerm);
+        setInfoForRelations(existing);
 
         if (DEBUG_ENABLED) {
-            LOG.debug("<== GlossaryService.create() : {}", saved);
+            LOG.debug("<== GlossaryService.create() : {}", existing);
         }
-        return saved;
+        return existing;
     }
 
     public List<AtlasGlossaryTerm> createTerms(List<AtlasGlossaryTerm> 
glossaryTerm) throws AtlasBaseException {
@@ -340,14 +352,13 @@ public class GlossaryService {
             } catch (AtlasBaseException e) {
                 LOG.debug("Glossary term had no immediate attr updates. 
Exception: {}", e.getMessage());
             } finally {
-                // TODO: Manage remaining term relations
-                processRelations(atlasGlossaryTerm, existing);
+                glossaryTermUtils.processTermRelations(atlasGlossaryTerm, 
existing, GlossaryUtils.RelationshipOperation.UPDATE);
             }
 
         }
 
         updated = dataAccess.load(atlasGlossaryTerm);
-        setDisplayTextForRelations(updated);
+        setInfoForRelations(updated);
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.updateTerm() : {}", updated);
         }
@@ -362,7 +373,15 @@ public class GlossaryService {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid 
is null/empty");
         }
 
+        AtlasGlossaryTerm existing = 
dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+
+        // Remove term from Glossary
+        glossaryTermUtils.processTermRelations(existing, existing, 
GlossaryUtils.RelationshipOperation.DELETE);
+
+        // Remove term associations with Entities
+        glossaryTermUtils.processTermDissociation(existing, 
existing.getAssignedEntities());
 
+        // Now delete the term
         dataAccess.delete(termGuid);
 
         if (DEBUG_ENABLED) {
@@ -370,35 +389,28 @@ public class GlossaryService {
         }
     }
 
-    public void assignTermToEntities(String termGuid, 
Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException {
+    public void assignTermToEntities(String termGuid, 
List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
+        if (DEBUG_ENABLED) {
+            LOG.debug("==> GlossaryService.assignTermToEntities({}, {})", 
termGuid, relatedObjectIds);
+        }
         AtlasGlossaryTerm glossaryTerm = 
dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+        glossaryTermUtils.processTermAssignments(glossaryTerm, 
relatedObjectIds);
 
-        if (Objects.nonNull(glossaryTerm)) {
-            Set<AtlasEntityHeader> assignedEntities = 
glossaryTerm.getAssignedEntities();
-            for (AtlasEntityHeader entityHeader : entityHeaders) {
-                if (CollectionUtils.isNotEmpty(assignedEntities) && 
assignedEntities.contains(entityHeader)) continue;
-                if (DEBUG_ENABLED) {
-                    LOG.debug("Assigning term guid={}, to entity guid = {}", 
termGuid, entityHeader.getGuid());
-                }
-                createRelationship(defineTermAssignment(termGuid, 
entityHeader));
-            }
+        if (DEBUG_ENABLED) {
+            LOG.debug("<== GlossaryService.assignTermToEntities()");
         }
     }
 
-    public void removeTermFromEntities(String termGuid, 
Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException {
+    public void removeTermFromEntities(String termGuid, 
List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> GlossaryService.removeTermFromEntities({}, {})", 
termGuid, relatedObjectIds);
+        }
+
         AtlasGlossaryTerm glossaryTerm = 
dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+        glossaryTermUtils.processTermDissociation(glossaryTerm, 
relatedObjectIds);
 
-        if (Objects.nonNull(glossaryTerm)) {
-            for (AtlasEntityHeader entityHeader : entityHeaders) {
-                if (DEBUG_ENABLED) {
-                    LOG.debug("Removing term guid={}, from entity guid = {}", 
termGuid, entityHeader.getGuid());
-                }
-                Object relationGuid = 
entityHeader.getAttribute("relationGuid");
-                if (Objects.isNull(relationGuid)) {
-                    throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"EntityHeader is missing mandatory attribute relation guid");
-                }
-                relationshipStore.deleteById((String) relationGuid);
-            }
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== GlossaryService.removeTermFromEntities()");
         }
     }
 
@@ -413,11 +425,10 @@ public class GlossaryService {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"categoryGuid is null/empty");
         }
 
-
         AtlasGlossaryCategory atlasGlossary = 
getAtlasGlossaryCategorySkeleton(categoryGuid);
         AtlasGlossaryCategory ret           = dataAccess.load(atlasGlossary);
 
-        setDisplayTextForRelations(ret);
+        setInfoForRelations(ret);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.getCategory() : {}", ret);
@@ -433,28 +444,26 @@ public class GlossaryService {
         if (Objects.isNull(glossaryCategory)) {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"GlossaryCategory definition missing");
         }
-        if (Objects.isNull(glossaryCategory.getQualifiedName())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"GlossaryCategory qualifiedName is mandatory");
+        if (Objects.isNull(glossaryCategory.getAnchor())) {
+            throw new 
AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
+        }
+        if (StringUtils.isEmpty(glossaryCategory.getQualifiedName())) {
+            String displayName  = glossaryCategory.getDisplayName();
+            String glossaryName = 
glossaryCategory.getAnchor().getDisplayText();
+            if (StringUtils.isEmpty(displayName) || 
StringUtils.isEmpty(glossaryName)) {
+                throw new 
AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_QUALIFIED_NAME_CANT_BE_DERIVED);
+            } else {
+                glossaryCategory.setQualifiedName(displayName + "@" + 
glossaryName);
+            }
         }
 
         AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory);
 
         // Attempt relation creation
-        if (Objects.nonNull(glossaryCategory.getAnchor())) {
-            processCategoryAnchor(glossaryCategory, saved);
-        }
-
-        if (Objects.nonNull(glossaryCategory.getParentCategory())) {
-            processParentCategory(glossaryCategory, saved);
-        }
-
-        if 
(CollectionUtils.isNotEmpty(glossaryCategory.getChildrenCategories())) {
-            processCategoryChildren(glossaryCategory, saved);
-        }
-
+        glossaryCategoryUtils.processCategoryRelations(glossaryCategory, 
saved, GlossaryUtils.RelationshipOperation.CREATE);
         saved = dataAccess.load(glossaryCategory);
 
-        setDisplayTextForRelations(glossaryCategory);
+        setInfoForRelations(glossaryCategory);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.createCategory() : {}", saved);
@@ -502,7 +511,7 @@ public class GlossaryService {
             } catch (AtlasBaseException e) {
                 LOG.debug("No immediate attribute update. Exception: {}", 
e.getMessage());
             } finally {
-                processRelations(glossaryCategory, existing);
+                
glossaryCategoryUtils.processCategoryRelations(glossaryCategory, existing, 
GlossaryUtils.RelationshipOperation.UPDATE);
             }
         }
 
@@ -511,7 +520,7 @@ public class GlossaryService {
         }
         ret = dataAccess.load(glossaryCategory);
 
-        setDisplayTextForRelations(glossaryCategory);
+        setInfoForRelations(glossaryCategory);
 
         return ret;
     }
@@ -524,12 +533,17 @@ public class GlossaryService {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category 
guid is null/empty");
         }
 
+        AtlasGlossaryCategory existing = 
dataAccess.load(getAtlasGlossaryCategorySkeleton(categoryGuid));
+
+        // Delete all relations
+        glossaryCategoryUtils.processCategoryRelations(existing, existing, 
GlossaryUtils.RelationshipOperation.DELETE);
+
+        // Now delete the category
         dataAccess.delete(categoryGuid);
 
         if (DEBUG_ENABLED) {
             LOG.debug("<== GlossaryService.deleteCategory()");
         }
-
     }
 
     public List<AtlasGlossaryTerm> getGlossaryTerms(String glossaryGuid, int 
offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
@@ -585,8 +599,8 @@ public class GlossaryService {
         if (CollectionUtils.isNotEmpty(categories)) {
             if (sortOrder != null) {
                 categories.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
-                               
o1.getDisplayText().compareTo(o2.getDisplayText()) :
-                               
o2.getDisplayText().compareTo(o1.getDisplayText()));
+                                                    
o1.getDisplayText().compareTo(o2.getDisplayText()) :
+                                                    
o2.getDisplayText().compareTo(o1.getDisplayText()));
             }
             ret = new PaginationHelper<>(categories, offset, 
limit).getPaginatedList();
         } else {
@@ -615,8 +629,8 @@ public class GlossaryService {
         if (CollectionUtils.isNotEmpty(glossaryCategory.getTerms())) {
             if (sortOrder != null) {
                 terms.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
-                                                    
o1.getDisplayText().compareTo(o2.getDisplayText()) :
-                                                    
o2.getDisplayText().compareTo(o1.getDisplayText()));
+                                               
o1.getDisplayText().compareTo(o2.getDisplayText()) :
+                                               
o2.getDisplayText().compareTo(o1.getDisplayText()));
             }
             ret = new PaginationHelper<>(terms, offset, 
limit).getPaginatedList();
         } else {
@@ -682,15 +696,15 @@ public class GlossaryService {
         return ret;
     }
 
-    public List<AtlasEntityHeader> getAssignedEntities(final String termGuid, 
int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+    public List<AtlasRelatedObjectId> getAssignedEntities(final String 
termGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException 
{
         if (Objects.isNull(termGuid)) {
             throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid 
is null/empty");
         }
 
-        AtlasGlossaryTerm      glossaryTerm     = 
dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
-        Set<AtlasEntityHeader> assignedEntities = 
glossaryTerm.getAssignedEntities();
+        AtlasGlossaryTerm         glossaryTerm     = 
dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+        Set<AtlasRelatedObjectId> assignedEntities = 
glossaryTerm.getAssignedEntities();
 
-        List<AtlasEntityHeader> ret;
+        List<AtlasRelatedObjectId> ret;
         if (CollectionUtils.isNotEmpty(assignedEntities)) {
             ret = new ArrayList<>(assignedEntities);
             if (sortOrder != null) {
@@ -712,79 +726,69 @@ public class GlossaryService {
         return glossary;
     }
 
-    private void processAssignedEntities(final AtlasGlossaryTerm newObj, final 
AtlasGlossaryTerm existing) throws AtlasBaseException {
-        if (newObj.equals(existing)) return;
+    private void deleteCategories(final AtlasGlossary existing, final 
Set<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(categories)) {
+            if (DEBUG_ENABLED) {
+                LOG.debug("Deleting categories within glossary guid = {}", 
existing.getGuid());
+            }
+            for (AtlasRelatedCategoryHeader category : categories) {
+                // Delete category
+                deleteCategory(category.getCategoryGuid());
+            }
+        }
+    }
 
-        if (CollectionUtils.isNotEmpty(newObj.getAssignedEntities())) {
-            for (AtlasEntityHeader entityHeader : 
newObj.getAssignedEntities()) {
-                createRelationship(defineTermAssignment(existing.getGuid(), 
entityHeader));
+    private void deleteTerms(final AtlasGlossary existing, final 
Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
+        if (CollectionUtils.isNotEmpty(terms)) {
+            if (DEBUG_ENABLED) {
+                LOG.debug("Deleting terms within glossary guid = {}", 
existing.getGuid());
+            }
+            for (AtlasRelatedTermHeader term : terms) {
+                // Delete the term
+                deleteTerm(term.getTermGuid());
             }
         }
     }
 
-    private void setDisplayTextForRelations(final AtlasGlossary ret) throws 
AtlasBaseException {
+    private AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String 
termGuid) {
+        AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
+        glossaryTerm.setGuid(termGuid);
+        return glossaryTerm;
+    }
+
+    private AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final 
String categoryGuid) {
+        AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
+        glossaryCategory.setGuid(categoryGuid);
+        return glossaryCategory;
+    }
+
+    private void setInfoForRelations(final AtlasGlossary ret) throws 
AtlasBaseException {
         if (Objects.nonNull(ret.getTerms())) {
-            setDisplayNameForTerms(ret.getTerms());
+            setInfoForTerms(ret.getTerms());
         }
 
         if (Objects.nonNull(ret.getCategories())) {
-            setDisplayNameForRelatedCategories(ret.getCategories());
+            setInfoForRelatedCategories(ret.getCategories());
         }
     }
 
-    private void setDisplayTextForRelations(final AtlasGlossaryTerm ret) 
throws AtlasBaseException {
+    private void setInfoForRelations(final AtlasGlossaryTerm ret) throws 
AtlasBaseException {
         if (Objects.nonNull(ret.getCategories())) {
             setDisplayNameForTermCategories(ret.getCategories());
         }
         if (Objects.nonNull(ret.getRelatedTerms())) {
             for (Map.Entry<AtlasGlossaryTerm.Relation, 
Set<AtlasRelatedTermHeader>> entry : ret.getRelatedTerms().entrySet()) {
-                setDisplayNameForTerms(entry.getValue());
+                setInfoForTerms(entry.getValue());
             }
         }
     }
 
-    private void setDisplayTextForRelations(final AtlasGlossaryCategory 
glossaryCategory) throws AtlasBaseException {
+    private void setInfoForRelations(final AtlasGlossaryCategory 
glossaryCategory) throws AtlasBaseException {
         if (Objects.nonNull(glossaryCategory.getChildrenCategories())) {
-            
setDisplayNameForRelatedCategories(glossaryCategory.getChildrenCategories());
+            
setInfoForRelatedCategories(glossaryCategory.getChildrenCategories());
         }
         if (Objects.nonNull(glossaryCategory.getTerms())) {
-            setDisplayNameForTerms(glossaryCategory.getTerms());
-        }
-    }
-
-    private void processRelations(final AtlasGlossaryTerm newObj, final 
AtlasGlossaryTerm existing) throws AtlasBaseException {
-        boolean hasRelatedTerms     = newObj.hasTerms();
-        boolean hasTermAnchor       = Objects.nonNull(newObj.getAnchor());
-        boolean hasCategories       = Objects.nonNull(newObj.getCategories());
-
-        if (hasTermAnchor) {
-            processTermAnchor(newObj, existing);
-        }
-        if (hasRelatedTerms) {
-            processRelatedTerms(newObj, existing);
-        }
-        if (hasCategories) {
-            processAssociatedCategories(newObj, existing);
-        }
-    }
-
-    private void processRelations(final AtlasGlossaryCategory newObj, final 
AtlasGlossaryCategory existing) throws AtlasBaseException {
-        boolean hasParent   = Objects.nonNull(newObj.getParentCategory());
-        boolean hasChildren = Objects.nonNull(newObj.getChildrenCategories());
-        boolean hasAnchor   = Objects.nonNull(newObj.getAnchor());
-        boolean hasTerms    = Objects.nonNull(newObj.getTerms());
-
-        if (hasAnchor) {
-            processCategoryAnchor(newObj, existing);
-        }
-        if (hasParent) {
-            processParentCategory(newObj, existing);
-        }
-        if (hasChildren) {
-            processCategoryChildren(newObj, existing);
-        }
-        if (hasTerms) {
-            processAssociatedTerms(newObj, existing);
+            setInfoForTerms(glossaryCategory.getTerms());
         }
     }
 
@@ -798,17 +802,23 @@ public class GlossaryService {
         categorizationHeaders.forEach(c -> 
c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName()));
     }
 
-    private void setDisplayNameForRelatedCategories(final 
Set<AtlasRelatedCategoryHeader> categoryHeaders) throws AtlasBaseException {
+    private void setInfoForRelatedCategories(final 
Set<AtlasRelatedCategoryHeader> categoryHeaders) throws AtlasBaseException {
         List<AtlasGlossaryCategory> categories = categoryHeaders
-                                                    .stream()
-                                                    .map(id -> 
getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
-                                                    
.collect(Collectors.toList());
+                                                         .stream()
+                                                         .map(id -> 
getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
+                                                         
.collect(Collectors.toList());
         Map<String, AtlasGlossaryCategory> categoryMap = new HashMap<>();
         dataAccess.load(categories).forEach(c -> categoryMap.put(c.getGuid(), 
c));
-        categoryHeaders.forEach(c -> 
c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName()));
+        for (AtlasRelatedCategoryHeader c : categoryHeaders) {
+            AtlasGlossaryCategory category = 
categoryMap.get(c.getCategoryGuid());
+            c.setDisplayText(category.getDisplayName());
+            if (Objects.nonNull(category.getParentCategory())) {
+                
c.setParentCategoryGuid(category.getParentCategory().getCategoryGuid());
+            }
+        }
     }
 
-    private void setDisplayNameForTerms(final Set<AtlasRelatedTermHeader> 
termHeaders) throws AtlasBaseException {
+    private void setInfoForTerms(final Set<AtlasRelatedTermHeader> 
termHeaders) throws AtlasBaseException {
         List<AtlasGlossaryTerm> terms = termHeaders
                                                 .stream()
                                                 .map(id -> 
getAtlasGlossaryTermSkeleton(id.getTermGuid()))
@@ -819,301 +829,6 @@ public class GlossaryService {
         termHeaders.forEach(t -> 
t.setDisplayText(termMap.get(t.getTermGuid()).getDisplayName()));
     }
 
-    private void processAssociatedCategories(final AtlasGlossaryTerm newObj, 
final AtlasGlossaryTerm existing) throws AtlasBaseException {
-        if (newObj.equals(existing)) return;
-
-        Set<AtlasTermCategorizationHeader> categories = newObj.getCategories();
-        if (Objects.nonNull(categories)) {
-            Set<AtlasTermCategorizationHeader> existingCategories = 
existing.getCategories();
-            for (AtlasTermCategorizationHeader category : categories) {
-                if (Objects.isNull(category.getCategoryGuid())) {
-                    throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"Linked category guid can't be empty");
-                } else {
-                    if (Objects.nonNull(existingCategories) && 
existingCategories.contains(category)) {
-                        if (DEBUG_ENABLED) {
-                            LOG.debug("Skipping linked category {}", 
category.getCategoryGuid());
-                        }
-                        continue;
-                    }
-                    if (DEBUG_ENABLED) {
-                        LOG.debug("Creating relation between term = {} and 
category = {}", existing.getGuid(), category.getCategoryGuid());
-                    }
-                    createRelationship(defineCategorizedTerm(category, 
existing.getGuid()));
-                }
-            }
-        }
-    }
-
-    private void processAssociatedTerms(final AtlasGlossaryCategory 
glossaryCategory, final AtlasGlossaryCategory existing) throws 
AtlasBaseException {
-        if (Objects.equals(glossaryCategory.getTerms(), existing.getTerms())) 
return;
-
-        for (AtlasRelatedTermHeader linkedTerm : glossaryCategory.getTerms()) {
-            if (Objects.isNull(linkedTerm.getTermGuid())) {
-                throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"Linked term guid can't be empty");
-            } else {
-                // Don't process existing child relation
-                Set<AtlasRelatedTermHeader> existingTerms = 
existing.getTerms();
-                if (Objects.nonNull(existingTerms) && 
existingTerms.contains(linkedTerm)) {
-                    if (DEBUG_ENABLED) {
-                        LOG.debug("Skipping linked term {}", 
linkedTerm.getTermGuid());
-                    }
-                    continue;
-                }
-
-                if (DEBUG_ENABLED) {
-                    LOG.debug("Creating relation between category = {} and 
term = {}", existing.getGuid(), linkedTerm.getTermGuid());
-                }
-                // TODO: Accept the relationship attributes as well
-                createRelationship(defineCategorizedTerm(existing.getGuid(), 
linkedTerm));
-            }
-        }
-    }
-
-    private void processTermAnchor(final AtlasGlossaryTerm glossaryTerm, final 
AtlasGlossaryTerm saved) throws AtlasBaseException {
-        if (Objects.isNull(glossaryTerm.getAnchor())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"glossaryTerm anchor mandatory attribute");
-        }
-
-        if (Objects.equals(glossaryTerm.getAnchor(), saved.getAnchor())) 
return;
-
-        if (Objects.isNull(glossaryTerm.getAnchor().getGlossaryGuid())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Anchor 
guid can't be empty");
-        } else {
-            if (DEBUG_ENABLED) {
-                LOG.debug("Creating relation between glossary = {} and term = 
{}", glossaryTerm.getAnchor().getGlossaryGuid(), saved.getGuid());
-            }
-            
createRelationship(defineTermAnchorRelation(glossaryTerm.getAnchor().getGlossaryGuid(),
 saved.getGuid()));
-        }
-    }
-
-    private void processCategoryAnchor(final AtlasGlossaryCategory newObj, 
final AtlasGlossaryCategory existing) throws AtlasBaseException {
-        if (Objects.isNull(newObj.getAnchor())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"glossaryCategory anchor mandatory attribute");
-        }
-
-        // Don't process anchor if no change
-        if (Objects.equals(newObj.getAnchor(), existing.getAnchor())) return;
-
-        if (Objects.isNull(newObj.getAnchor().getGlossaryGuid())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category 
anchor guid can't be empty");
-        } else {
-            if (DEBUG_ENABLED) {
-                LOG.debug("Creating relation between glossary = {} and 
category = {}", newObj.getAnchor().getGlossaryGuid(), existing.getGuid());
-            }
-            
createRelationship(defineCategoryAnchorRelation(newObj.getAnchor().getGlossaryGuid(),
 existing.getGuid()));
-        }
-    }
-
-    private void processRelatedTerms(final AtlasGlossaryTerm incomingObj, 
final AtlasGlossaryTerm savedObj) throws AtlasBaseException {
-        if (incomingObj.hasTerms()) {
-            for (Map.Entry<AtlasGlossaryTerm.Relation, 
Set<AtlasRelatedTermHeader>> entry : incomingObj.getRelatedTerms().entrySet()) {
-                AtlasGlossaryTerm.Relation  relation = entry.getKey();
-                Set<AtlasRelatedTermHeader> terms    = entry.getValue();
-                if (DEBUG_ENABLED) {
-                    LOG.debug("Creating relation {}", relation);
-                    LOG.debug("Related Term count = {}", terms.size());
-                }
-                if (Objects.nonNull(terms)) {
-                    for (AtlasRelatedTermHeader atlasGlossaryTerm : terms) {
-                        
createRelationship(defineTermRelation(relation.getRelationName(), 
savedObj.getGuid(), atlasGlossaryTerm));
-                    }
-                }
-            }
-        }
-        // TODO: Process other term relations as well
-    }
-
-    private void processCategoryChildren(final AtlasGlossaryCategory newObj, 
final AtlasGlossaryCategory existing) throws AtlasBaseException {
-        for (AtlasRelatedCategoryHeader childCategory : 
newObj.getChildrenCategories()) {
-            if (Objects.isNull(childCategory.getCategoryGuid())) {
-                throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, 
"Child category guid can't be empty");
-            } else {
-                // Don't process existing child relation
-                Set<AtlasRelatedCategoryHeader> existingChildren = 
existing.getChildrenCategories();
-                if (Objects.nonNull(existingChildren) && 
existingChildren.contains(childCategory)) {
-                    if (DEBUG_ENABLED) {
-                        LOG.debug("Skipping category child {}", 
childCategory.getCategoryGuid());
-                    }
-                    continue;
-                }
-
-                if (DEBUG_ENABLED) {
-                    LOG.debug("Creating relation between glossary = {} and 
term = {}", existing.getGuid(), childCategory.getCategoryGuid());
-                }
-                // TODO: Accept the relationship attributes as well
-                
createRelationship(defineCategoryHierarchyLink(existing.getGuid(), 
childCategory));
-            }
-        }
-    }
-
-    private void processParentCategory(final AtlasGlossaryCategory newObj, 
final AtlasGlossaryCategory existing) throws AtlasBaseException {
-        // Don't process unchanged parent
-        if (Objects.equals(newObj.getParentCategory(), 
existing.getParentCategory())) return;
-
-        if (Objects.isNull(newObj.getParentCategory().getCategoryGuid())) {
-            throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Parent 
category guid can't be empty");
-        } else {
-            if (DEBUG_ENABLED) {
-                LOG.debug("Creating category hierarchy b/w parent = {} and 
child = {}", newObj.getParentCategory().getCategoryGuid(), existing.getGuid());
-            }
-            
createRelationship(defineCategoryHierarchyLink(newObj.getParentCategory(), 
newObj.getGuid()));
-        }
-    }
-
-    private Map<String, List<AtlasGlossaryTerm>> loadTerms(final 
Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> relatedTerms,
-                                                           final int offset,
-                                                           final int limit,
-                                                           final SortOrder 
sortOrder) throws AtlasBaseException {
-        Map<String, List<AtlasGlossaryTerm>> ret = new HashMap<>();
-
-        for (Map.Entry<AtlasGlossaryTerm.Relation, 
Set<AtlasRelatedTermHeader>> entry : relatedTerms.entrySet()) {
-            ret.put(entry.getKey().getRelationAttrName(), 
loadTerms(entry.getValue(), offset, limit, sortOrder));
-        }
-
-        return ret;
-    }
-
-    private List<AtlasGlossaryTerm> loadTerms(final 
Set<AtlasRelatedTermHeader> terms,
-                                              final int offset,
-                                              final int limit,
-                                              final SortOrder sortOrder) 
throws AtlasBaseException {
-        return loadTerms(new ArrayList<>(terms), offset, limit, sortOrder);
-    }
-
-    private List<AtlasGlossaryTerm> loadTerms(final 
List<AtlasRelatedTermHeader> terms,
-                                              final int offset,
-                                              final int limit,
-                                              final SortOrder sortOrder) 
throws AtlasBaseException {
-        Objects.requireNonNull(terms);
-        List<AtlasGlossaryTerm> ret;
-
-        ret = terms.stream().map(id -> 
getAtlasGlossaryTermSkeleton(id.getTermGuid())).collect(Collectors.toList());
-        Iterable<AtlasGlossaryTerm> loadedTerms = dataAccess.load(ret);
-        ret.clear();
-        loadedTerms.forEach(ret::add);
-        // Sort only when needed
-        if (sortOrder != null) {
-            ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
-                                         
o1.getDisplayName().compareTo(o2.getDisplayName()) :
-                                         
o2.getDisplayName().compareTo(o1.getDisplayName()));
-        }
-        return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
-    }
-
-    private List<AtlasGlossaryCategory> loadCategories(final 
Set<AtlasRelatedCategoryHeader> categories,
-                                                       final int offset,
-                                                       final int limit,
-                                                       final SortOrder 
sortOrder) throws AtlasBaseException {
-        return loadCategories(new ArrayList<>(categories), offset, limit, 
sortOrder);
-    }
-
-    private List<AtlasGlossaryCategory> loadCategories(final 
List<AtlasRelatedCategoryHeader> categories,
-                                                       final int offset,
-                                                       final int limit,
-                                                       final SortOrder 
sortOrder) throws AtlasBaseException {
-        Objects.requireNonNull(categories);
-        List<AtlasGlossaryCategory> ret = categories.stream()
-                                                    .map(id -> 
getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
-                                                    
.collect(Collectors.toList());
-        Iterable<AtlasGlossaryCategory> loadedCategories = 
dataAccess.load(ret);
-        ret.clear();
-        loadedCategories.forEach(ret::add);
-
-        // Sort only when needed
-        if (sortOrder != null) {
-            ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
-                                         
o1.getDisplayName().compareTo(o2.getDisplayName()) :
-                                         
o2.getDisplayName().compareTo(o1.getDisplayName()));
-        }
-
-        return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
-    }
-
-    private AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String 
termGuid) {
-        AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
-        glossaryTerm.setGuid(termGuid);
-        return glossaryTerm;
-    }
-
-    private AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final 
String categoryGuid) {
-        AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
-        glossaryCategory.setGuid(categoryGuid);
-        return glossaryCategory;
-    }
-
-    private void createRelationship(AtlasRelationship relationship) throws 
AtlasBaseException {
-        try {
-            relationshipStore.create(relationship);
-        } catch (AtlasBaseException e) {
-            if 
(!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIP_ALREADY_EXISTS)) {
-                throw e;
-            }
-        }
-    }
-
-    private AtlasRelationship defineTermAnchorRelation(String glossaryGuid, 
String termGuid) {
-        return new AtlasRelationship(TERM_ANCHOR, new 
AtlasObjectId(glossaryGuid), new AtlasObjectId(termGuid));
-    }
-
-    private AtlasRelationship defineCategoryAnchorRelation(String 
glossaryGuid, String categoryGuid) {
-        return new AtlasRelationship(CATEGORY_ANCHOR, new 
AtlasObjectId(glossaryGuid), new AtlasObjectId(categoryGuid));
-    }
-
-    private AtlasRelationship defineCategoryHierarchyLink(String 
parentCategoryGuid, AtlasRelatedCategoryHeader childCategory) {
-        AtlasRelationship relationship = new 
AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategoryGuid), 
new AtlasObjectId(childCategory.getCategoryGuid()));
-        relationship.setAttribute("description", 
childCategory.getDescription());
-        return relationship;
-    }
-
-    private AtlasRelationship defineCategoryHierarchyLink(final 
AtlasRelatedCategoryHeader parentCategory, final String childGuid) {
-        AtlasRelationship relationship = new 
AtlasRelationship(CATEGORY_HIERARCHY, new 
AtlasObjectId(parentCategory.getCategoryGuid()), new AtlasObjectId(childGuid));
-        relationship.setAttribute("description", 
parentCategory.getDescription());
-        return relationship;
-    }
-
-    private AtlasRelationship defineCategorizedTerm(String categoryGuid, 
AtlasRelatedTermHeader relatedTermId) {
-        AtlasRelationship relationship = new 
AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(categoryGuid), new 
AtlasObjectId(relatedTermId.getTermGuid()));
-
-        relationship.setAttribute("expression", relatedTermId.getExpression());
-        relationship.setAttribute("description", 
relatedTermId.getDescription());
-        relationship.setAttribute("steward", relatedTermId.getSteward());
-        relationship.setAttribute("source", relatedTermId.getSource());
-        if (Objects.nonNull(relatedTermId.getStatus())) {
-            relationship.setAttribute("status", 
relatedTermId.getStatus().name());
-        }
-
-        return relationship;
-    }
-
-    private AtlasRelationship 
defineCategorizedTerm(AtlasTermCategorizationHeader relatedCategoryId, String 
termId) {
-        AtlasRelationship relationship = new 
AtlasRelationship(TERM_CATEGORIZATION, new 
AtlasObjectId(relatedCategoryId.getCategoryGuid()), new AtlasObjectId(termId));
-
-        relationship.setAttribute("description", 
relatedCategoryId.getDescription());
-        if (Objects.nonNull(relatedCategoryId.getStatus())) {
-            relationship.setAttribute("status", 
relatedCategoryId.getStatus().name());
-        }
-
-        return relationship;
-    }
-
-    private AtlasRelationship defineTermRelation(String relation, String 
end1TermGuid, AtlasRelatedTermHeader end2RelatedTerm) {
-        AtlasRelationship relationship = new AtlasRelationship(relation, new 
AtlasObjectId(end1TermGuid), new AtlasObjectId(end2RelatedTerm.getTermGuid()));
-
-        relationship.setAttribute("expression", 
end2RelatedTerm.getExpression());
-        relationship.setAttribute("description", 
end2RelatedTerm.getDescription());
-        relationship.setAttribute("steward", end2RelatedTerm.getSteward());
-        relationship.setAttribute("source", end2RelatedTerm.getSource());
-        if (Objects.nonNull(end2RelatedTerm.getStatus())) {
-            relationship.setAttribute("status", 
end2RelatedTerm.getStatus().name());
-        }
-
-        return relationship;
-    }
-
-    private AtlasRelationship defineTermAssignment(String termGuid, 
AtlasEntityHeader entityHeader) {
-        return new AtlasRelationship(TERM_ASSIGNMENT, new 
AtlasObjectId(termGuid), new AtlasObjectId(entityHeader.getGuid()));
-    }
-
     static class PaginationHelper<T> {
         private int     pageStart;
         private int     pageEnd;
@@ -1156,4 +871,5 @@ public class GlossaryService {
             return pageStart <= maxSize;
         }
     }
+
 }

Reply via email to