Commit 66f8ae16 by apoorvnaik

ATLAS-2679: Update qualifiedName category hierarchy corresponding to any change to category

Change-Id: I4cddcfe76eabcf7ee705b60848521158bb33a8a5
parent 801db28b
...@@ -26,6 +26,7 @@ import java.util.Arrays; ...@@ -26,6 +26,7 @@ import java.util.Arrays;
public enum AtlasErrorCode { public enum AtlasErrorCode {
NO_SEARCH_RESULTS(204, "ATLAS-204-00-001", "Given search filter {0} did not yield any results"), NO_SEARCH_RESULTS(204, "ATLAS-204-00-001", "Given search filter {0} did not yield any results"),
DATA_ACCESS_SAVE_FAILED(204, "ATLAS-204-00-002", "Save failed: {0} has no updates"),
UNKNOWN_TYPE(400, "ATLAS-400-00-001", "Unknown type {0} for {1}.{2}"), UNKNOWN_TYPE(400, "ATLAS-400-00-001", "Unknown type {0} for {1}.{2}"),
CIRCULAR_REFERENCE(400, "ATLAS-400-00-002", "{0}: invalid supertypes - circular reference back to self {1}"), CIRCULAR_REFERENCE(400, "ATLAS-400-00-002", "{0}: invalid supertypes - circular reference back to self {1}"),
...@@ -144,6 +145,7 @@ public enum AtlasErrorCode { ...@@ -144,6 +145,7 @@ public enum AtlasErrorCode {
INVALID_CHILD_CATEGORY_DIFFERENT_GLOSSARY(400, "ATLAS-400-00-07F", "Invalid child category relationship: Child category (guid = {0}) belongs to different glossary"), INVALID_CHILD_CATEGORY_DIFFERENT_GLOSSARY(400, "ATLAS-400-00-07F", "Invalid child category relationship: Child category (guid = {0}) belongs to different glossary"),
INVALID_TERM_DISSOCIATION(400, "ATLAS-400-00-080", "Given term (guid={0}) is not associated to entity(guid={1})"), INVALID_TERM_DISSOCIATION(400, "ATLAS-400-00-080", "Given term (guid={0}) is not associated to entity(guid={1})"),
ATTRIBUTE_TYPE_INVALID(400, "ATLAS-400-00-081", "{0}.{1}: invalid attribute type. Attribute cannot be of type classification"), ATTRIBUTE_TYPE_INVALID(400, "ATLAS-400-00-081", "{0}.{1}: invalid attribute type. Attribute cannot be of type classification"),
MISSING_CATEGORY_DISPLAY_NAME(400, "ATLAS-400-00-082", "Category displayName is empty/null"),
UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"), UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"),
...@@ -196,7 +198,6 @@ public enum AtlasErrorCode { ...@@ -196,7 +198,6 @@ public enum AtlasErrorCode {
SQOOP_HOOK(500, "ATLAS-500-00-00F", "SqoopHook: {0}"), SQOOP_HOOK(500, "ATLAS-500-00-00F", "SqoopHook: {0}"),
HIVE_HOOK(500, "ATLAS-500-00-010", "HiveHook: {0}"), HIVE_HOOK(500, "ATLAS-500-00-010", "HiveHook: {0}"),
HIVE_HOOK_METASTORE_BRIDGE(500, "ATLAS-500-00-011", "HiveHookMetaStoreBridge: {0}"), HIVE_HOOK_METASTORE_BRIDGE(500, "ATLAS-500-00-011", "HiveHookMetaStoreBridge: {0}"),
DATA_ACCESS_SAVE_FAILED(500, "ATLAS-500-00-012", "Save failed: {0}"),
DATA_ACCESS_LOAD_FAILED(500, "ATLAS-500-00-013", "Load failed: {0}"), DATA_ACCESS_LOAD_FAILED(500, "ATLAS-500-00-013", "Load failed: {0}"),
ENTITY_NOTIFICATION_FAILED(500, "ATLAS-500-00-014", "Notification failed for operation: {0} : {1}"); ENTITY_NOTIFICATION_FAILED(500, "ATLAS-500-00-014", "Notification failed for operation: {0} : {1}");
......
...@@ -146,12 +146,10 @@ public class AtlasGlossary extends AtlasGlossaryBaseObject { ...@@ -146,12 +146,10 @@ public class AtlasGlossary extends AtlasGlossaryBaseObject {
@Override @Override
protected StringBuilder toString(final StringBuilder sb) { protected StringBuilder toString(final StringBuilder sb) {
sb.append("{"); sb.append(", language='").append(language).append('\'');
sb.append("language='").append(language).append('\'');
sb.append(", usage='").append(usage).append('\''); sb.append(", usage='").append(usage).append('\'');
sb.append(", terms=").append(terms); sb.append(", terms=").append(terms);
sb.append(", categories=").append(categories); sb.append(", categories=").append(categories);
sb.append('}');
return sb; return sb;
} }
...@@ -234,11 +232,8 @@ public class AtlasGlossary extends AtlasGlossaryBaseObject { ...@@ -234,11 +232,8 @@ public class AtlasGlossary extends AtlasGlossaryBaseObject {
@Override @Override
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
sb.append("{");
super.toString(sb);
sb.append(", termInfo=").append(termInfo); sb.append(", termInfo=").append(termInfo);
sb.append(", categoryInfo=").append(categoryInfo); sb.append(", categoryInfo=").append(categoryInfo);
sb.append('}');
return sb; return sb;
} }
......
...@@ -29,13 +29,13 @@ import java.util.Objects; ...@@ -29,13 +29,13 @@ import java.util.Objects;
public abstract class AtlasGlossaryBaseObject extends AtlasBaseModelObject { public abstract class AtlasGlossaryBaseObject extends AtlasBaseModelObject {
// Core attributes // Core attributes
private String qualifiedName;
protected String displayName; protected String displayName;
protected String shortDescription; protected String shortDescription;
protected String longDescription; protected String longDescription;
// Classifications // Classifications
protected List<AtlasClassification> classifications; protected List<AtlasClassification> classifications;
private String qualifiedName;
public AtlasGlossaryBaseObject() { public AtlasGlossaryBaseObject() {
} }
...@@ -129,13 +129,11 @@ public abstract class AtlasGlossaryBaseObject extends AtlasBaseModelObject { ...@@ -129,13 +129,11 @@ public abstract class AtlasGlossaryBaseObject extends AtlasBaseModelObject {
@Override @Override
protected StringBuilder toString(final StringBuilder sb) { protected StringBuilder toString(final StringBuilder sb) {
sb.append("{"); sb.append(", qualifiedName='").append(qualifiedName).append('\'');
sb.append("displayName='").append(displayName).append('\''); sb.append(", displayName='").append(displayName).append('\'');
sb.append(", shortDescription='").append(shortDescription).append('\''); sb.append(", shortDescription='").append(shortDescription).append('\'');
sb.append(", longDescription='").append(longDescription).append('\''); sb.append(", longDescription='").append(longDescription).append('\'');
sb.append(", classifications=").append(classifications); sb.append(", classifications=").append(classifications);
sb.append(", qualifiedName='").append(qualifiedName).append('\'');
sb.append('}');
return sb; return sb;
} }
......
...@@ -138,16 +138,10 @@ public class AtlasGlossaryCategory extends AtlasGlossaryBaseObject { ...@@ -138,16 +138,10 @@ public class AtlasGlossaryCategory extends AtlasGlossaryBaseObject {
@Override @Override
protected StringBuilder toString(final StringBuilder sb) { protected StringBuilder toString(final StringBuilder sb) {
sb.append("{");
sb.append("displayName='").append(getDisplayName()).append('\'');
sb.append(", shortDescription='").append(getShortDescription()).append('\'');
sb.append(", longDescription='").append(getLongDescription()).append('\'');
sb.append(", anchor=").append(anchor); sb.append(", anchor=").append(anchor);
sb.append(", parentCategory=").append(parentCategory); sb.append(", parentCategory=").append(parentCategory);
sb.append(", childrenCategories=").append(childrenCategories); sb.append(", childrenCategories=").append(childrenCategories);
sb.append(", terms=").append(terms); sb.append(", terms=").append(terms);
sb.append(", classifications=").append(getClassifications());
sb.append('}');
return sb; return sb;
} }
......
...@@ -376,7 +376,6 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject { ...@@ -376,7 +376,6 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject {
@Override @Override
protected StringBuilder toString(final StringBuilder sb) { protected StringBuilder toString(final StringBuilder sb) {
sb.append("{");
sb.append("examples=").append(examples); sb.append("examples=").append(examples);
sb.append(", abbreviation='").append(abbreviation).append('\''); sb.append(", abbreviation='").append(abbreviation).append('\'');
sb.append(", usage='").append(usage).append('\''); sb.append(", usage='").append(usage).append('\'');
...@@ -396,7 +395,6 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject { ...@@ -396,7 +395,6 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject {
sb.append(", classifies=").append(classifies); sb.append(", classifies=").append(classifies);
sb.append(", validValues=").append(validValues); sb.append(", validValues=").append(validValues);
sb.append(", validValuesFor=").append(validValuesFor); sb.append(", validValuesFor=").append(validValuesFor);
sb.append('}');
return sb; return sb;
} }
......
...@@ -19,7 +19,9 @@ package org.apache.atlas.glossary; ...@@ -19,7 +19,9 @@ package org.apache.atlas.glossary;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.glossary.AtlasGlossary;
import org.apache.atlas.model.glossary.AtlasGlossaryCategory; import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
...@@ -51,68 +53,103 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -51,68 +53,103 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
super(relationshipStore, typeRegistry, dataAccess); super(relationshipStore, typeRegistry, dataAccess);
} }
public void processCategoryRelations(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { public Map<String, AtlasGlossaryCategory> processCategoryRelations(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory, RelationshipOperation op) throws AtlasBaseException {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("==> GlossaryCategoryUtils.processCategoryRelations({}, {}, {})", updatedCategory, existing, op); LOG.debug("==> GlossaryCategoryUtils.processCategoryRelations({}, {}, {})", storeObject, updatedCategory, op);
} }
processCategoryAnchor(updatedCategory, existing, op); Map<String, AtlasGlossaryCategory> impactedCategories = new HashMap<>();
processParentCategory(updatedCategory, existing, op);
processCategoryChildren(updatedCategory, existing, op); processCategoryAnchor(storeObject, updatedCategory, op, impactedCategories);
processAssociatedTerms(updatedCategory, existing, op); processParentCategory(storeObject, updatedCategory, op, impactedCategories);
processCategoryChildren(storeObject, updatedCategory, op, impactedCategories);
processAssociatedTerms(storeObject, updatedCategory, op);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryCategoryUtils.processCategoryRelations()"); LOG.debug("<== GlossaryCategoryUtils.processCategoryRelations(): {}", impactedCategories);
} }
return impactedCategories;
} }
private void processCategoryAnchor(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { private void processCategoryAnchor(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory,
RelationshipOperation op, Map<String, AtlasGlossaryCategory> impactedCategories) throws AtlasBaseException {
if (Objects.isNull(updatedCategory.getAnchor()) && op != RelationshipOperation.DELETE) { if (Objects.isNull(updatedCategory.getAnchor()) && op != RelationshipOperation.DELETE) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
} }
AtlasGlossaryHeader existingAnchor = storeObject.getAnchor();
AtlasGlossaryHeader updatedCategoryAnchor = updatedCategory.getAnchor();
switch (op) { switch (op) {
case CREATE: case CREATE:
if (StringUtils.isEmpty(updatedCategoryAnchor.getGlossaryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID);
} else {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new category anchor, category = {}, glossary = {}", existing.getGuid(), updatedCategory.getAnchor().getDisplayText()); LOG.debug("Creating new category anchor, category = {}, glossary = {}", storeObject.getGuid(), updatedCategory.getAnchor().getGlossaryGuid());
} }
// Derive the qualifiedName
String anchorGlossaryGuid = updatedCategory.getAnchor().getGlossaryGuid(); String anchorGlossaryGuid = updatedCategory.getAnchor().getGlossaryGuid();
createRelationship(defineCategoryAnchorRelation(anchorGlossaryGuid, existing.getGuid())); AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(anchorGlossaryGuid));
storeObject.setQualifiedName(storeObject.getDisplayName()+ "@" + glossary.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
}
createRelationship(defineCategoryAnchorRelation(anchorGlossaryGuid, storeObject.getGuid()));
}
break; break;
case UPDATE: case UPDATE:
if (!Objects.equals(updatedCategory.getAnchor(), existing.getAnchor())) { if (!Objects.equals(existingAnchor, updatedCategoryAnchor)) {
if (Objects.isNull(updatedCategory.getAnchor().getGlossaryGuid())) { if (Objects.isNull(updatedCategory.getAnchor().getGlossaryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID); throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID);
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating category anchor, category = {}, currAnchor = {}, newAnchor = {}", existing.getGuid(), LOG.debug("Updating category anchor, currAnchor = {}, newAnchor = {} and category = {}",
existing.getAnchor().getDisplayText(), updatedCategory.getAnchor().getDisplayText()); storeObject.getAnchor().getGlossaryGuid(),
updatedCategory.getAnchor().getGlossaryGuid(),
storeObject.getGuid());
}
relationshipStore.deleteById(storeObject.getAnchor().getRelationGuid());
// Derive the qualifiedName when anchor changes
String anchorGlossaryGuid = updatedCategory.getAnchor().getGlossaryGuid();
AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(anchorGlossaryGuid));
storeObject.setQualifiedName(storeObject.getDisplayName()+ "@" + glossary.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
} }
relationshipStore.deleteById(existing.getAnchor().getRelationGuid());
createRelationship(defineCategoryAnchorRelation(updatedCategory.getAnchor().getGlossaryGuid(), existing.getGuid())); createRelationship(defineCategoryAnchorRelation(updatedCategory.getAnchor().getGlossaryGuid(), storeObject.getGuid()));
// Anchor changed, qualifiedName of children needs an update
updateChildCategories(storeObject, storeObject.getChildrenCategories(), impactedCategories, false);
} }
break; break;
case DELETE: case DELETE:
if (Objects.nonNull(existing.getAnchor())) { if (Objects.nonNull(storeObject.getAnchor())) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting category anchor"); LOG.debug("Deleting category anchor");
} }
relationshipStore.deleteById(existing.getAnchor().getRelationGuid()); relationshipStore.deleteById(storeObject.getAnchor().getRelationGuid());
} }
break; break;
} }
} }
private void processParentCategory(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { private void processParentCategory(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory,
RelationshipOperation op, Map<String, AtlasGlossaryCategory> impactedCategories) throws AtlasBaseException {
AtlasRelatedCategoryHeader newParent = updatedCategory.getParentCategory(); AtlasRelatedCategoryHeader newParent = updatedCategory.getParentCategory();
AtlasRelatedCategoryHeader existingParent = existing.getParentCategory(); AtlasRelatedCategoryHeader existingParent = storeObject.getParentCategory();
switch (op) { switch (op) {
case CREATE: case CREATE:
if (Objects.nonNull(newParent)) { if (Objects.nonNull(newParent)) {
if (DEBUG_ENABLED) { processNewParent(storeObject, newParent, impactedCategories);
LOG.debug("Creating new parent, category = {}, parent = {}", existing.getGuid(), newParent.getDisplayText());
}
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
} }
break; break;
case UPDATE: case UPDATE:
...@@ -124,18 +161,12 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -124,18 +161,12 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} }
if (Objects.isNull(existingParent)) { if (Objects.isNull(existingParent)) {
if (DEBUG_ENABLED) { processNewParent(storeObject, newParent, impactedCategories);
LOG.debug("Creating new parent, category = {}, parent = {}", existing.getGuid(), newParent.getDisplayText());
}
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
} else if (Objects.isNull(newParent)) { } else if (Objects.isNull(newParent)) {
if (DEBUG_ENABLED) { processParentRemoval(storeObject, updatedCategory, existingParent, impactedCategories);
LOG.debug("Removing category parent, category = {}, parent = {}", existing.getGuid(), existingParent.getDisplayText());
}
relationshipStore.deleteById(existingParent.getRelationGuid());
} else { } else {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating category parent, category = {}, currParent = {}, newParent = {}", existing.getGuid(), existingParent.getDisplayText(), newParent.getDisplayText()); LOG.debug("Updating category parent, category = {}, currParent = {}, newParent = {}", storeObject.getGuid(), existingParent.getDisplayText(), newParent.getDisplayText());
} }
AtlasRelationship parentRelationship = relationshipStore.getById(existingParent.getRelationGuid()); AtlasRelationship parentRelationship = relationshipStore.getById(existingParent.getRelationGuid());
if (existingParent.getCategoryGuid().equals(newParent.getCategoryGuid())) { if (existingParent.getCategoryGuid().equals(newParent.getCategoryGuid())) {
...@@ -144,48 +175,83 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -144,48 +175,83 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} else { } else {
// Delete link to existing parent and link to new parent // Delete link to existing parent and link to new parent
relationshipStore.deleteById(parentRelationship.getGuid()); relationshipStore.deleteById(parentRelationship.getGuid());
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid())); createRelationship(defineCategoryHierarchyLink(newParent, storeObject.getGuid()));
} }
} }
break; break;
case DELETE: case DELETE:
if (Objects.nonNull(existingParent)) { if (Objects.nonNull(existingParent)) {
processParentRemoval(storeObject, updatedCategory, existingParent, impactedCategories);
}
break;
}
}
private void processNewParent(AtlasGlossaryCategory storeObject, AtlasRelatedCategoryHeader newParent, Map<String, AtlasGlossaryCategory> impactedCategories) throws AtlasBaseException {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Removing category parent, category = {}, parent = {}", existing.getGuid(), existingParent.getDisplayText()); LOG.debug("Creating new parent, category = {}, parent = {}", storeObject.getGuid(), newParent.getDisplayText());
} }
relationshipStore.deleteById(existingParent.getRelationGuid()); createRelationship(defineCategoryHierarchyLink(newParent, storeObject.getGuid()));
// New parent added, qualifiedName needs recomputation
// Derive the qualifiedName of the Glossary
AtlasGlossaryCategory parentCategory = dataAccess.load(getAtlasGlossaryCategorySkeleton(newParent.getCategoryGuid()));
storeObject.setQualifiedName(storeObject.getDisplayName() + "." + parentCategory.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
} }
break;
updateChildCategories(storeObject, storeObject.getChildrenCategories(), impactedCategories, false);
}
private void processParentRemoval(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory, AtlasRelatedCategoryHeader existingParent, Map<String, AtlasGlossaryCategory> impactedCategories) throws AtlasBaseException {
if (DEBUG_ENABLED) {
LOG.debug("Removing category parent, category = {}, parent = {}", storeObject.getGuid(), existingParent.getDisplayText());
}
relationshipStore.deleteById(existingParent.getRelationGuid());
// Parent deleted, qualifiedName needs recomputation
// Derive the qualifiedName of the Glossary
String anchorGlossaryGuid = updatedCategory.getAnchor().getGlossaryGuid();
AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(anchorGlossaryGuid));
storeObject.setQualifiedName(storeObject.getDisplayName() + "@" + glossary.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
} }
updateChildCategories(storeObject, storeObject.getChildrenCategories(), impactedCategories, false);
} }
private void processAssociatedTerms(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { private void processAssociatedTerms(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory, RelationshipOperation op) throws AtlasBaseException {
Map<String, AtlasRelatedTermHeader> newTerms = getTerms(updatedCategory); Map<String, AtlasRelatedTermHeader> newTerms = getTerms(updatedCategory);
Map<String, AtlasRelatedTermHeader> existingTerms = getTerms(existing); Map<String, AtlasRelatedTermHeader> existingTerms = getTerms(storeObject);
switch (op) { switch (op) {
case CREATE: case CREATE:
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), LOG.debug("Creating term relation with category = {}, terms = {}", storeObject.getDisplayName(),
Objects.nonNull(newTerms) ? newTerms.size() : "none"); Objects.nonNull(newTerms) ? newTerms.size() : "none");
} }
createTermCategorizationRelationships(existing, newTerms.values()); createTermCategorizationRelationships(storeObject, newTerms.values());
break; break;
case UPDATE: case UPDATE:
if (MapUtils.isEmpty(existingTerms)) { if (MapUtils.isEmpty(existingTerms)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), LOG.debug("Creating term relation with category = {}, terms = {}", storeObject.getDisplayName(),
Objects.nonNull(newTerms) ? newTerms.size() : "none"); Objects.nonNull(newTerms) ? newTerms.size() : "none");
} }
createTermCategorizationRelationships(existing, newTerms.values()); createTermCategorizationRelationships(storeObject, newTerms.values());
break; break;
} }
if (MapUtils.isEmpty(newTerms)) { if (MapUtils.isEmpty(newTerms)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting term relation with category = {}, terms = {}", existing.getDisplayName(), existingTerms.size()); LOG.debug("Deleting term relation with category = {}, terms = {}", storeObject.getDisplayName(), existingTerms.size());
} }
deleteTermCategorizationRelationships(existing, existingTerms.values()); deleteTermCategorizationRelationships(storeObject, existingTerms.values());
break; break;
} }
...@@ -194,24 +260,24 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -194,24 +260,24 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
.stream() .stream()
.filter(t -> !existingTerms.containsKey(t.getTermGuid())) .filter(t -> !existingTerms.containsKey(t.getTermGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
createTermCategorizationRelationships(existing, toCreate); createTermCategorizationRelationships(storeObject, toCreate);
Set<AtlasRelatedTermHeader> toUpdate = newTerms Set<AtlasRelatedTermHeader> toUpdate = newTerms
.values() .values()
.stream() .stream()
.filter(t -> updatedExistingTermRelation(existingTerms, t)) .filter(t -> updatedExistingTermRelation(existingTerms, t))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
updateTermCategorizationRelationships(existing, toUpdate); updateTermCategorizationRelationships(storeObject, toUpdate);
Set<AtlasRelatedTermHeader> toDelete = existingTerms Set<AtlasRelatedTermHeader> toDelete = existingTerms
.values() .values()
.stream() .stream()
.filter(t -> !newTerms.containsKey(t.getTermGuid())) .filter(t -> !newTerms.containsKey(t.getTermGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
deleteTermCategorizationRelationships(existing, toDelete); deleteTermCategorizationRelationships(storeObject, toDelete);
break; break;
case DELETE: case DELETE:
deleteTermCategorizationRelationships(existing, existingTerms.values()); deleteTermCategorizationRelationships(storeObject, existingTerms.values());
break; break;
} }
} }
...@@ -220,7 +286,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -220,7 +286,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
return Objects.nonNull(term.getRelationGuid()) && !existingTerms.get(term.getTermGuid()).equals(term); return Objects.nonNull(term.getRelationGuid()) && !existingTerms.get(term.getTermGuid()).equals(term);
} }
private Map<String, AtlasRelatedTermHeader> getTerms(final AtlasGlossaryCategory category) { private Map<String, AtlasRelatedTermHeader> getTerms(AtlasGlossaryCategory category) {
if (Objects.nonNull(category.getTerms())) { if (Objects.nonNull(category.getTerms())) {
Map<String, AtlasRelatedTermHeader> map = new HashMap<>(); Map<String, AtlasRelatedTermHeader> map = new HashMap<>();
for (AtlasRelatedTermHeader t : category.getTerms()) { for (AtlasRelatedTermHeader t : category.getTerms()) {
...@@ -236,9 +302,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -236,9 +302,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
else return Collections.emptyMap(); else return Collections.emptyMap();
} }
private void createTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { private void createTermCategorizationRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) { if (CollectionUtils.isNotEmpty(terms)) {
Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms(); Set<AtlasRelatedTermHeader> existingTerms = storeObject.getTerms();
for (AtlasRelatedTermHeader term : terms) { for (AtlasRelatedTermHeader term : terms) {
if (Objects.isNull(term.getTermGuid())) { if (Objects.isNull(term.getTermGuid())) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_TERM_ID_FOR_CATEGORIZATION); throw new AtlasBaseException(AtlasErrorCode.MISSING_TERM_ID_FOR_CATEGORIZATION);
...@@ -250,19 +316,19 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -250,19 +316,19 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
continue; continue;
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating relation between category = {} and term = {}", existing.getGuid(), term.getDisplayText()); LOG.debug("Creating relation between category = {} and term = {}", storeObject.getGuid(), term.getDisplayText());
} }
createRelationship(defineCategorizedTerm(existing.getGuid(), term)); createRelationship(defineCategorizedTerm(storeObject.getGuid(), term));
} }
} }
} }
} }
private void updateTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { private void updateTermCategorizationRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) { if (CollectionUtils.isNotEmpty(terms)) {
for (AtlasRelatedTermHeader term : terms) { for (AtlasRelatedTermHeader term : terms) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating term relation with category = {}, term = {}", existing.getDisplayName(), term.getDisplayText()); LOG.debug("Updating term relation with category = {}, term = {}", storeObject.getDisplayName(), term.getDisplayText());
} }
AtlasRelationship relationship = relationshipStore.getById(term.getRelationGuid()); AtlasRelationship relationship = relationshipStore.getById(term.getRelationGuid());
updateRelationshipAttributes(relationship, term); updateRelationshipAttributes(relationship, term);
...@@ -271,44 +337,53 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -271,44 +337,53 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} }
} }
private void deleteTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { private void deleteTermCategorizationRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) { if (CollectionUtils.isNotEmpty(terms)) {
for (AtlasRelatedTermHeader term : terms) { for (AtlasRelatedTermHeader term : terms) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), term.getDisplayText()); LOG.debug("Creating term relation with category = {}, terms = {}", storeObject.getDisplayName(), term.getDisplayText());
} }
relationshipStore.deleteById(term.getRelationGuid()); relationshipStore.deleteById(term.getRelationGuid());
} }
} }
} }
private void processCategoryChildren(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { private void processCategoryChildren(AtlasGlossaryCategory storeObject, AtlasGlossaryCategory updatedCategory, RelationshipOperation op, Map<String, AtlasGlossaryCategory> impactedCategories) throws AtlasBaseException {
Map<String, AtlasRelatedCategoryHeader> newChildren = getChildren(updatedCategory); Map<String, AtlasRelatedCategoryHeader> newChildren = getChildren(updatedCategory);
Map<String, AtlasRelatedCategoryHeader> existingChildren = getChildren(existing); Map<String, AtlasRelatedCategoryHeader> existingChildren = getChildren(storeObject);
switch (op) { switch (op) {
case CREATE: case CREATE:
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(), LOG.debug("Creating new children, category = {}, children = {}", storeObject.getDisplayName(),
Objects.nonNull(newChildren) ? newChildren.size() : "none"); Objects.nonNull(newChildren) ? newChildren.size() : "none");
} }
createCategoryRelationships(existing, newChildren.values()); createCategoryRelationships(storeObject, newChildren.values());
// New children added, qualifiedName needs recomputation
updateChildCategories(storeObject, newChildren.values(), impactedCategories, false);
break; break;
case UPDATE: case UPDATE:
// Create new children // Create new children
if (MapUtils.isEmpty(existingChildren)) { if (MapUtils.isEmpty(existingChildren)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(), LOG.debug("Creating new children, category = {}, children = {}", storeObject.getDisplayName(),
Objects.nonNull(newChildren) ? newChildren.size() : "none"); Objects.nonNull(newChildren) ? newChildren.size() : "none");
} }
createCategoryRelationships(existing, newChildren.values()); createCategoryRelationships(storeObject, newChildren.values());
// New children added, qualifiedName needs recomputation
updateChildCategories(storeObject, newChildren.values(), impactedCategories, false);
break; break;
} }
// Delete current children // Delete current children
if (MapUtils.isEmpty(newChildren)) { if (MapUtils.isEmpty(newChildren)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting children, category = {}, children = {}", existing.getDisplayName(), existingChildren.size()); LOG.debug("Deleting children, category = {}, children = {}", storeObject.getDisplayName(), existingChildren.size());
} }
deleteCategoryRelationships(existing, existingChildren.values()); deleteCategoryRelationships(storeObject, existingChildren.values());
// Re-compute the qualifiedName for all children
updateChildCategories(storeObject, existingChildren.values(), impactedCategories, true);
break; break;
} }
...@@ -317,24 +392,26 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -317,24 +392,26 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
.stream() .stream()
.filter(c -> !existingChildren.containsKey(c.getCategoryGuid())) .filter(c -> !existingChildren.containsKey(c.getCategoryGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
createCategoryRelationships(existing, toCreate); createCategoryRelationships(storeObject, toCreate);
// New children added, qualifiedName needs recomputation
updateChildCategories(storeObject, toCreate, impactedCategories, false);
Set<AtlasRelatedCategoryHeader> toUpdate = newChildren Set<AtlasRelatedCategoryHeader> toUpdate = newChildren
.values() .values()
.stream() .stream()
.filter(c -> updatedExistingCategoryRelation(existingChildren, c)) .filter(c -> updatedExistingCategoryRelation(existingChildren, c))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
updateCategoryRelationships(existing, toUpdate); updateCategoryRelationships(storeObject, toUpdate);
Set<AtlasRelatedCategoryHeader> toDelete = existingChildren Set<AtlasRelatedCategoryHeader> toDelete = existingChildren
.values() .values()
.stream() .stream()
.filter(c -> !newChildren.containsKey(c.getCategoryGuid())) .filter(c -> !newChildren.containsKey(c.getCategoryGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
deleteCategoryRelationships(existing, toDelete); deleteCategoryRelationships(storeObject, toDelete);
break; break;
case DELETE: case DELETE:
deleteCategoryRelationships(existing, existingChildren.values()); deleteCategoryRelationships(storeObject, existingChildren.values());
break; break;
} }
} }
...@@ -343,7 +420,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -343,7 +420,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingChildren.get(header.getCategoryGuid())); return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingChildren.get(header.getCategoryGuid()));
} }
private Map<String, AtlasRelatedCategoryHeader> getChildren(final AtlasGlossaryCategory category) { private Map<String, AtlasRelatedCategoryHeader> getChildren(AtlasGlossaryCategory category) {
if (Objects.nonNull(category.getChildrenCategories())) { if (Objects.nonNull(category.getChildrenCategories())) {
Map<String, AtlasRelatedCategoryHeader> map = new HashMap<>(); Map<String, AtlasRelatedCategoryHeader> map = new HashMap<>();
for (AtlasRelatedCategoryHeader c : category.getChildrenCategories()) { for (AtlasRelatedCategoryHeader c : category.getChildrenCategories()) {
...@@ -357,9 +434,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -357,9 +434,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
else return Collections.emptyMap(); else return Collections.emptyMap();
} }
private void createCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException { private void createCategoryRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(newChildren)) { if (CollectionUtils.isNotEmpty(newChildren)) {
Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories(); Set<AtlasRelatedCategoryHeader> existingChildren = storeObject.getChildrenCategories();
for (AtlasRelatedCategoryHeader child : newChildren) { for (AtlasRelatedCategoryHeader child : newChildren) {
if (Objects.nonNull(existingChildren) && existingChildren.contains(child)) { if (Objects.nonNull(existingChildren) && existingChildren.contains(child)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
...@@ -376,11 +453,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -376,11 +453,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
childCategory.setGuid(child.getCategoryGuid()); childCategory.setGuid(child.getCategoryGuid());
childCategory = dataAccess.load(childCategory); childCategory = dataAccess.load(childCategory);
if (StringUtils.equals(existing.getAnchor().getGlossaryGuid(), childCategory.getAnchor().getGlossaryGuid())) { if (StringUtils.equals(storeObject.getAnchor().getGlossaryGuid(), childCategory.getAnchor().getGlossaryGuid())) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new child, category = {}, child = {}", existing.getDisplayName(), child.getDisplayText()); LOG.debug("Creating new child, category = {}, child = {}", storeObject.getDisplayName(), child.getDisplayText());
} }
createRelationship(defineCategoryHierarchyLink(existing.getGuid(), child)); createRelationship(defineCategoryHierarchyLink(storeObject.getGuid(), child));
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.INVALID_CHILD_CATEGORY_DIFFERENT_GLOSSARY, child.getCategoryGuid()); throw new AtlasBaseException(AtlasErrorCode.INVALID_CHILD_CATEGORY_DIFFERENT_GLOSSARY, child.getCategoryGuid());
} }
...@@ -389,11 +466,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -389,11 +466,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} }
} }
private void updateCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException { private void updateCategoryRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(toUpdate)) { if (CollectionUtils.isNotEmpty(toUpdate)) {
for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) { for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating child, category = {}, child = {}", existing.getDisplayName(), categoryHeader.getDisplayText()); LOG.debug("Updating child, category = {}, child = {}", storeObject.getDisplayName(), categoryHeader.getDisplayText());
} }
AtlasRelationship childRelationship = relationshipStore.getById(categoryHeader.getRelationGuid()); AtlasRelationship childRelationship = relationshipStore.getById(categoryHeader.getRelationGuid());
updateRelationshipAttributes(childRelationship, categoryHeader); updateRelationshipAttributes(childRelationship, categoryHeader);
...@@ -402,11 +479,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -402,11 +479,11 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} }
} }
private void deleteCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException { private void deleteCategoryRelationships(AtlasGlossaryCategory storeObject, Collection<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(existingChildren)) { if (CollectionUtils.isNotEmpty(existingChildren)) {
for (AtlasRelatedCategoryHeader child : existingChildren) { for (AtlasRelatedCategoryHeader child : existingChildren) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting child, category = {}, child = {}", existing.getDisplayName(), child.getDisplayText()); LOG.debug("Deleting child, category = {}, child = {}", storeObject.getDisplayName(), child.getDisplayText());
} }
relationshipStore.deleteById(child.getRelationGuid()); relationshipStore.deleteById(child.getRelationGuid());
} }
...@@ -453,4 +530,56 @@ public class GlossaryCategoryUtils extends GlossaryUtils { ...@@ -453,4 +530,56 @@ public class GlossaryCategoryUtils extends GlossaryUtils {
} }
} }
private void updateChildCategories(AtlasGlossaryCategory parentCategory, Collection<AtlasRelatedCategoryHeader> childCategories, Map<String, AtlasGlossaryCategory> impactedCategories, boolean isParentRemoved) throws AtlasBaseException {
if (CollectionUtils.isEmpty(childCategories)) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Recomputing qualifiedName for {} children of category(guid={}, qualifiedName={})", childCategories.size(), parentCategory.getGuid(), parentCategory.getQualifiedName());
}
String parentAnchorGuid = parentCategory.getAnchor().getGlossaryGuid();
for (AtlasRelatedCategoryHeader childCategoryHeader : childCategories) {
AtlasGlossaryCategory child = dataAccess.load(getAtlasGlossaryCategorySkeleton(childCategoryHeader.getCategoryGuid()));
String qualifiedName = child.getDisplayName() + ".";
String childAnchorGuid = child.getAnchor().getGlossaryGuid();
if (isParentRemoved) {
if (LOG.isDebugEnabled()) {
LOG.debug("Parent removed, deriving qualifiedName using Glossary");
}
AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(childAnchorGuid));
qualifiedName += glossary.getQualifiedName();
child.setParentCategory(null);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Using parent to derive qualifiedName");
}
qualifiedName += parentCategory.getQualifiedName();
}
child.setQualifiedName(qualifiedName);
if (!StringUtils.equals(childAnchorGuid, parentAnchorGuid)){
if (LOG.isDebugEnabled()) {
LOG.debug("Child anchor guid({}) doesn't match parent anchor guid({}). Updating child anchor", childAnchorGuid, parentAnchorGuid);
}
// Remove old glossary relation
relationshipStore.deleteById(child.getAnchor().getRelationGuid());
// Link to new glossary
createRelationship(defineCategoryAnchorRelation(parentAnchorGuid, child.getGuid()));
// Update the child's anchor GUID
child.getAnchor().setGlossaryGuid(parentAnchorGuid);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", qualifiedName);
}
// Collect all affected/impacted categories in this accumulator. All impacted categories will be saved as a part of post processing
impactedCategories.put(child.getGuid(), child);
updateChildCategories(child, child.getChildrenCategories(), impactedCategories, false);
}
}
} }
...@@ -50,6 +50,10 @@ import java.util.Objects; ...@@ -50,6 +50,10 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.atlas.glossary.GlossaryUtils.getAtlasGlossaryCategorySkeleton;
import static org.apache.atlas.glossary.GlossaryUtils.getAtlasGlossaryTermSkeleton;
import static org.apache.atlas.glossary.GlossaryUtils.getGlossarySkeleton;
@Service @Service
public class GlossaryService { public class GlossaryService {
private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class); private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class);
...@@ -91,7 +95,7 @@ public class GlossaryService { ...@@ -91,7 +95,7 @@ public class GlossaryService {
List<AtlasGlossary> ret; List<AtlasGlossary> ret;
List<String> guidsToLoad = paginationHelper.getPaginatedList(); List<String> guidsToLoad = paginationHelper.getPaginatedList();
if (CollectionUtils.isNotEmpty(guidsToLoad)) { if (CollectionUtils.isNotEmpty(guidsToLoad)) {
ret = guidsToLoad.stream().map(GlossaryService::getGlossarySkeleton).collect(Collectors.toList()); ret = guidsToLoad.stream().map(GlossaryUtils::getGlossarySkeleton).collect(Collectors.toList());
Iterable<AtlasGlossary> glossaries = dataAccess.load(ret); Iterable<AtlasGlossary> glossaries = dataAccess.load(ret);
ret.clear(); ret.clear();
...@@ -139,13 +143,13 @@ public class GlossaryService { ...@@ -139,13 +143,13 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_ALREADY_EXISTS, atlasGlossary.getQualifiedName()); throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_ALREADY_EXISTS, atlasGlossary.getQualifiedName());
} }
AtlasGlossary saved = dataAccess.save(atlasGlossary); AtlasGlossary storeObject = dataAccess.save(atlasGlossary);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.createGlossary() : {}", saved); LOG.debug("<== GlossaryService.createGlossary() : {}", storeObject);
} }
return saved; return storeObject;
} }
/** /**
...@@ -238,20 +242,20 @@ public class GlossaryService { ...@@ -238,20 +242,20 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty");
} }
AtlasGlossary ret = dataAccess.load(atlasGlossary); AtlasGlossary storeObject = dataAccess.load(atlasGlossary);
if (!ret.equals(atlasGlossary)) { if (!storeObject.equals(atlasGlossary)) {
atlasGlossary.setGuid(ret.getGuid()); atlasGlossary.setGuid(storeObject.getGuid());
atlasGlossary.setQualifiedName(ret.getQualifiedName()); atlasGlossary.setQualifiedName(storeObject.getQualifiedName());
ret = dataAccess.save(atlasGlossary); storeObject = dataAccess.save(atlasGlossary);
setInfoForRelations(ret); setInfoForRelations(storeObject);
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.updateGlossary() : {}", ret); LOG.debug("<== GlossaryService.updateGlossary() : {}", storeObject);
} }
return ret; return storeObject;
} }
@GraphTransaction @GraphTransaction
...@@ -263,13 +267,13 @@ public class GlossaryService { ...@@ -263,13 +267,13 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
} }
AtlasGlossary existing = dataAccess.load(getGlossarySkeleton(glossaryGuid)); AtlasGlossary storeObject = dataAccess.load(getGlossarySkeleton(glossaryGuid));
Set<AtlasRelatedTermHeader> terms = existing.getTerms(); Set<AtlasRelatedTermHeader> terms = storeObject.getTerms();
deleteTerms(existing, terms); deleteTerms(storeObject, terms);
Set<AtlasRelatedCategoryHeader> categories = existing.getCategories(); Set<AtlasRelatedCategoryHeader> categories = storeObject.getCategories();
deleteCategories(existing, categories); deleteCategories(storeObject, categories);
// Once all relations are deleted, then delete the Glossary // Once all relations are deleted, then delete the Glossary
dataAccess.delete(glossaryGuid); dataAccess.delete(glossaryGuid);
...@@ -314,31 +318,26 @@ public class GlossaryService { ...@@ -314,31 +318,26 @@ public class GlossaryService {
if (Objects.isNull(glossaryTerm.getAnchor())) { if (Objects.isNull(glossaryTerm.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
} }
if (StringUtils.isEmpty(glossaryTerm.getQualifiedName())) { if (StringUtils.isEmpty(glossaryTerm.getDisplayName())) {
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); throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_QUALIFIED_NAME_CANT_BE_DERIVED);
} else {
glossaryTerm.setQualifiedName(displayName + "@" + glossaryName);
}
} }
// This might fail for the case when the term's qualifiedName has been updated and the duplicate request comes in with old name
if (termExists(glossaryTerm)) { if (termExists(glossaryTerm)) {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_ALREADY_EXISTS, glossaryTerm.getQualifiedName()); throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_ALREADY_EXISTS, glossaryTerm.getQualifiedName());
} }
AtlasGlossaryTerm existing = dataAccess.save(glossaryTerm); AtlasGlossaryTerm storeObject = dataAccess.save(glossaryTerm);
glossaryTermUtils.processTermRelations(glossaryTerm, existing, GlossaryUtils.RelationshipOperation.CREATE); glossaryTermUtils.processTermRelations(storeObject, glossaryTerm, GlossaryUtils.RelationshipOperation.CREATE);
// Re-load term after handling relations // Re-load term after handling relations
existing = dataAccess.load(glossaryTerm); storeObject = dataAccess.load(glossaryTerm);
setInfoForRelations(existing); setInfoForRelations(storeObject);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.create() : {}", existing); LOG.debug("<== GlossaryService.create() : {}", storeObject);
} }
return existing; return storeObject;
} }
@GraphTransaction @GraphTransaction
...@@ -378,28 +377,29 @@ public class GlossaryService { ...@@ -378,28 +377,29 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty");
} }
AtlasGlossaryTerm existing = dataAccess.load(atlasGlossaryTerm); AtlasGlossaryTerm storeObject = dataAccess.load(atlasGlossaryTerm);
AtlasGlossaryTerm updated = atlasGlossaryTerm; if (!storeObject.equals(atlasGlossaryTerm)) {
if (!existing.equals(updated)) {
try { try {
updated.setGuid(existing.getGuid()); atlasGlossaryTerm.setGuid(storeObject.getGuid());
updated.setQualifiedName(existing.getQualifiedName()); atlasGlossaryTerm.setQualifiedName(storeObject.getQualifiedName());
atlasGlossaryTerm = dataAccess.save(updated); storeObject = dataAccess.save(atlasGlossaryTerm);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
LOG.debug("Glossary term had no immediate attr updates. Exception: {}", e.getMessage()); LOG.debug("Glossary term had no immediate attr updates. Exception: {}", e.getMessage());
} finally { } finally {
glossaryTermUtils.processTermRelations(atlasGlossaryTerm, existing, GlossaryUtils.RelationshipOperation.UPDATE); glossaryTermUtils.processTermRelations(storeObject, atlasGlossaryTerm, GlossaryUtils.RelationshipOperation.UPDATE);
} }
} }
updated = dataAccess.load(atlasGlossaryTerm); storeObject = dataAccess.load(atlasGlossaryTerm);
setInfoForRelations(updated); setInfoForRelations(storeObject);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.updateTerm() : {}", updated); LOG.debug("<== GlossaryService.updateTerm() : {}", storeObject);
} }
return updated;
return storeObject;
} }
@GraphTransaction @GraphTransaction
...@@ -411,13 +411,13 @@ public class GlossaryService { ...@@ -411,13 +411,13 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
} }
AtlasGlossaryTerm existing = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid)); AtlasGlossaryTerm storeObject = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
// Remove term from Glossary // Remove term from Glossary
glossaryTermUtils.processTermRelations(existing, existing, GlossaryUtils.RelationshipOperation.DELETE); glossaryTermUtils.processTermRelations(storeObject, storeObject, GlossaryUtils.RelationshipOperation.DELETE);
// Remove term associations with Entities // Remove term associations with Entities
glossaryTermUtils.processTermDissociation(existing, existing.getAssignedEntities()); glossaryTermUtils.processTermDissociation(storeObject, storeObject.getAssignedEntities());
// Now delete the term // Now delete the term
dataAccess.delete(termGuid); dataAccess.delete(termGuid);
...@@ -489,33 +489,39 @@ public class GlossaryService { ...@@ -489,33 +489,39 @@ public class GlossaryService {
if (Objects.isNull(glossaryCategory.getAnchor())) { if (Objects.isNull(glossaryCategory.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
} }
if (StringUtils.isEmpty(glossaryCategory.getQualifiedName())) { if (Objects.isNull(glossaryCategory.getDisplayName())) {
String displayName = glossaryCategory.getDisplayName(); throw new AtlasBaseException(AtlasErrorCode.MISSING_CATEGORY_DISPLAY_NAME);
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);
}
} }
// This might fail for the case when the category's qualifiedName has been updated during a hierarchy change
// and the duplicate request comes in with old name
if (categoryExists(glossaryCategory)) { if (categoryExists(glossaryCategory)) {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_ALREADY_EXISTS, glossaryCategory.getQualifiedName()); throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_ALREADY_EXISTS, glossaryCategory.getQualifiedName());
} }
AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory); AtlasGlossaryCategory storeObject = dataAccess.save(glossaryCategory);
// Attempt relation creation and gather all impacted categories
Map<String, AtlasGlossaryCategory> impactedCategories = glossaryCategoryUtils.processCategoryRelations(storeObject, glossaryCategory, GlossaryUtils.RelationshipOperation.CREATE);
// Re save the categories in case any qualifiedName change has occurred
dataAccess.save(impactedCategories.values());
// Attempt relation creation // Since the current category is also affected, we need to update qualifiedName and save again
glossaryCategoryUtils.processCategoryRelations(glossaryCategory, saved, GlossaryUtils.RelationshipOperation.CREATE); if (!StringUtils.equals(glossaryCategory.getQualifiedName(), storeObject.getQualifiedName())) {
saved = dataAccess.load(glossaryCategory); glossaryCategory.setQualifiedName(storeObject.getQualifiedName());
storeObject = dataAccess.save(glossaryCategory);
} else {
storeObject = dataAccess.load(glossaryCategory);
}
setInfoForRelations(saved); setInfoForRelations(storeObject);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.createCategory() : {}", saved); LOG.debug("<== GlossaryService.createCategory() : {}", storeObject);
} }
return saved; return storeObject;
} }
@GraphTransaction @GraphTransaction
...@@ -552,30 +558,36 @@ public class GlossaryService { ...@@ -552,30 +558,36 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "DisplayName can't be null/empty");
} }
AtlasGlossaryCategory existing = dataAccess.load(glossaryCategory); AtlasGlossaryCategory storeObject = dataAccess.load(glossaryCategory);
AtlasGlossaryCategory ret = glossaryCategory;
if (!existing.equals(glossaryCategory)) { if (!storeObject.equals(glossaryCategory)) {
try { try {
glossaryCategory.setGuid(existing.getGuid()); glossaryCategory.setGuid(storeObject.getGuid());
glossaryCategory.setQualifiedName(existing.getQualifiedName()); glossaryCategory.setQualifiedName(storeObject.getQualifiedName());
ret = dataAccess.save(glossaryCategory); storeObject = dataAccess.save(glossaryCategory);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
LOG.debug("No immediate attribute update. Exception: {}", e.getMessage()); LOG.debug("No immediate attribute update. Exception: {}", e.getMessage());
} finally { } finally {
glossaryCategoryUtils.processCategoryRelations(glossaryCategory, existing, GlossaryUtils.RelationshipOperation.UPDATE); Map<String, AtlasGlossaryCategory> impactedCategories = glossaryCategoryUtils.processCategoryRelations(storeObject, glossaryCategory, GlossaryUtils.RelationshipOperation.UPDATE);
dataAccess.save(impactedCategories.values());
// Since the current category is also affected, we need to update qualifiedName and save again
if (!StringUtils.equals(glossaryCategory.getQualifiedName(), storeObject.getQualifiedName())){
glossaryCategory.setQualifiedName(storeObject.getQualifiedName());
storeObject = dataAccess.save(glossaryCategory);
} else {
storeObject = dataAccess.load(glossaryCategory);
}
} }
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.updateCategory() : {}", ret); LOG.debug("<== GlossaryService.updateCategory() : {}", storeObject);
} }
ret = dataAccess.load(glossaryCategory);
setInfoForRelations(ret); setInfoForRelations(storeObject);
return ret; return storeObject;
} }
@GraphTransaction @GraphTransaction
...@@ -587,10 +599,10 @@ public class GlossaryService { ...@@ -587,10 +599,10 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category guid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category guid is null/empty");
} }
AtlasGlossaryCategory existing = dataAccess.load(getAtlasGlossaryCategorySkeleton(categoryGuid)); AtlasGlossaryCategory storeObject = dataAccess.load(getAtlasGlossaryCategorySkeleton(categoryGuid));
// Delete all relations // Delete all relations
glossaryCategoryUtils.processCategoryRelations(existing, existing, GlossaryUtils.RelationshipOperation.DELETE); glossaryCategoryUtils.processCategoryRelations(storeObject, storeObject, GlossaryUtils.RelationshipOperation.DELETE);
// Now delete the category // Now delete the category
dataAccess.delete(categoryGuid); dataAccess.delete(categoryGuid);
...@@ -825,12 +837,6 @@ public class GlossaryService { ...@@ -825,12 +837,6 @@ public class GlossaryService {
return ret; return ret;
} }
private static AtlasGlossary getGlossarySkeleton(String glossaryGuid) {
AtlasGlossary glossary = new AtlasGlossary();
glossary.setGuid(glossaryGuid);
return glossary;
}
private boolean glossaryExists(AtlasGlossary atlasGlossary) { private boolean glossaryExists(AtlasGlossary atlasGlossary) {
AtlasVertex vertex = AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME), new HashMap<String, Object>() {{ AtlasVertex vertex = AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME), new HashMap<String, Object>() {{
put(QUALIFIED_NAME_ATTR, atlasGlossary.getQualifiedName()); put(QUALIFIED_NAME_ATTR, atlasGlossary.getQualifiedName());
...@@ -852,10 +858,10 @@ public class GlossaryService { ...@@ -852,10 +858,10 @@ public class GlossaryService {
return Objects.nonNull(vertex); return Objects.nonNull(vertex);
} }
private void deleteCategories(final AtlasGlossary existing, final Collection<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException { private void deleteCategories(final AtlasGlossary storeObject, final Collection<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(categories)) { if (CollectionUtils.isNotEmpty(categories)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting categories within glossary guid = {}", existing.getGuid()); LOG.debug("Deleting categories within glossary guid = {}", storeObject.getGuid());
} }
for (AtlasRelatedCategoryHeader category : categories) { for (AtlasRelatedCategoryHeader category : categories) {
// Delete category // Delete category
...@@ -864,10 +870,10 @@ public class GlossaryService { ...@@ -864,10 +870,10 @@ public class GlossaryService {
} }
} }
private void deleteTerms(final AtlasGlossary existing, final Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { private void deleteTerms(final AtlasGlossary storeObject, final Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) { if (CollectionUtils.isNotEmpty(terms)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting terms within glossary guid = {}", existing.getGuid()); LOG.debug("Deleting terms within glossary guid = {}", storeObject.getGuid());
} }
for (AtlasRelatedTermHeader term : terms) { for (AtlasRelatedTermHeader term : terms) {
// Delete the term // Delete the term
...@@ -876,18 +882,6 @@ public class GlossaryService { ...@@ -876,18 +882,6 @@ public class GlossaryService {
} }
} }
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 { private void setInfoForRelations(final AtlasGlossary ret) throws AtlasBaseException {
if (Objects.nonNull(ret.getTerms())) { if (Objects.nonNull(ret.getTerms())) {
setInfoForTerms(ret.getTerms()); setInfoForTerms(ret.getTerms());
......
...@@ -19,6 +19,7 @@ package org.apache.atlas.glossary; ...@@ -19,6 +19,7 @@ package org.apache.atlas.glossary;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.glossary.AtlasGlossary;
import org.apache.atlas.model.glossary.AtlasGlossaryTerm; import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
...@@ -53,14 +54,14 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -53,14 +54,14 @@ public class GlossaryTermUtils extends GlossaryUtils {
super(relationshipStore, typeRegistry, dataAccess); super(relationshipStore, typeRegistry, dataAccess);
} }
public void processTermRelations(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { public void processTermRelations(AtlasGlossaryTerm storeObject, AtlasGlossaryTerm updatedTerm, RelationshipOperation op) throws AtlasBaseException {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("==> GlossaryTermUtils.processTermRelations({}, {}, {})", updatedTerm, existing, op); LOG.debug("==> GlossaryTermUtils.processTermRelations({}, {}, {})", storeObject, updatedTerm, op);
} }
processTermAnchor(updatedTerm, existing, op); processTermAnchor(storeObject, updatedTerm, op);
processRelatedTerms(updatedTerm, existing, op); processRelatedTerms(storeObject, updatedTerm, op);
processAssociatedCategories(updatedTerm, existing, op); processAssociatedCategories(storeObject, updatedTerm, op);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryTermUtils.processTermRelations()"); LOG.debug("<== GlossaryTermUtils.processTermRelations()");
...@@ -130,12 +131,16 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -130,12 +131,16 @@ public class GlossaryTermUtils extends GlossaryUtils {
} }
} }
private boolean isRelationshipGuidSame(final AtlasRelatedObjectId existing, final AtlasRelatedObjectId relatedObjectId) { private boolean isRelationshipGuidSame(AtlasRelatedObjectId storeObject, AtlasRelatedObjectId relatedObjectId) {
return StringUtils.equals(relatedObjectId.getRelationshipGuid(), existing.getRelationshipGuid()); return StringUtils.equals(relatedObjectId.getRelationshipGuid(), storeObject.getRelationshipGuid());
} }
private void processTermAnchor(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { private void processTermAnchor(AtlasGlossaryTerm storeObject, AtlasGlossaryTerm updatedTerm, RelationshipOperation op) throws AtlasBaseException {
AtlasGlossaryHeader existingAnchor = existing.getAnchor(); if (Objects.isNull(updatedTerm.getAnchor()) && op != RelationshipOperation.DELETE) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
}
AtlasGlossaryHeader existingAnchor = storeObject.getAnchor();
AtlasGlossaryHeader updatedTermAnchor = updatedTerm.getAnchor(); AtlasGlossaryHeader updatedTermAnchor = updatedTerm.getAnchor();
switch (op) { switch (op) {
...@@ -144,9 +149,19 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -144,9 +149,19 @@ public class GlossaryTermUtils extends GlossaryUtils {
throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID); throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID);
} else { } else {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating relation between glossary = {} and term = {}", updatedTermAnchor.getGlossaryGuid(), existing.getDisplayName()); LOG.debug("Creating new term anchor, category = {}, glossary = {}", storeObject.getGuid(), updatedTerm.getAnchor().getGlossaryGuid());
}
// Derive the qualifiedName
String anchorGlossaryGuid = updatedTermAnchor.getGlossaryGuid();
AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(anchorGlossaryGuid));
storeObject.setQualifiedName(storeObject.getDisplayName() + "@" + glossary.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
} }
createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), existing.getGuid()));
createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), storeObject.getGuid()));
} }
break; break;
case UPDATE: case UPDATE:
...@@ -156,10 +171,23 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -156,10 +171,23 @@ public class GlossaryTermUtils extends GlossaryUtils {
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating relation between glossary = {} and term = {}", updatedTermAnchor.getGlossaryGuid(), existing.getDisplayName()); LOG.debug("Updating term anchor, currAnchor = {}, newAnchor = {} and term = {}",
existingAnchor.getGlossaryGuid(),
updatedTermAnchor.getGlossaryGuid(),
storeObject.getDisplayName());
} }
relationshipStore.deleteById(existingAnchor.getRelationGuid()); relationshipStore.deleteById(existingAnchor.getRelationGuid());
createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), existing.getGuid()));
// Derive the qualifiedName when anchor changes
String anchorGlossaryGuid = updatedTermAnchor.getGlossaryGuid();
AtlasGlossary glossary = dataAccess.load(getGlossarySkeleton(anchorGlossaryGuid));
storeObject.setQualifiedName(storeObject.getDisplayName() + "@" + glossary.getQualifiedName());
if (LOG.isDebugEnabled()) {
LOG.debug("Derived qualifiedName = {}", storeObject.getQualifiedName());
}
createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), storeObject.getGuid()));
} }
break; break;
case DELETE: case DELETE:
...@@ -173,9 +201,9 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -173,9 +201,9 @@ public class GlossaryTermUtils extends GlossaryUtils {
} }
} }
private void processRelatedTerms(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { private void processRelatedTerms(AtlasGlossaryTerm storeObject, AtlasGlossaryTerm updatedTerm, RelationshipOperation op) throws AtlasBaseException {
Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> newRelatedTerms = updatedTerm.getRelatedTerms(); Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> newRelatedTerms = updatedTerm.getRelatedTerms();
Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> existingRelatedTerms = existing.getRelatedTerms(); Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> existingRelatedTerms = storeObject.getRelatedTerms();
switch (op) { switch (op) {
case CREATE: case CREATE:
for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : newRelatedTerms.entrySet()) { for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : newRelatedTerms.entrySet()) {
...@@ -183,10 +211,10 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -183,10 +211,10 @@ public class GlossaryTermUtils extends GlossaryUtils {
Set<AtlasRelatedTermHeader> terms = entry.getValue(); Set<AtlasRelatedTermHeader> terms = entry.getValue();
if (Objects.nonNull(terms)) { if (Objects.nonNull(terms)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("{} relation {} for term = {}", op, relation, existing.getGuid()); LOG.debug("{} relation {} for term = {}", op, relation, storeObject.getGuid());
LOG.debug("Related Term count = {}", terms.size()); LOG.debug("Related Term count = {}", terms.size());
} }
createTermRelationships(existing, relation, terms); createTermRelationships(storeObject, relation, terms);
} }
} }
break; break;
...@@ -201,7 +229,7 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -201,7 +229,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
LOG.debug("Creating new term relations, relation = {}, terms = {}", relation, LOG.debug("Creating new term relations, relation = {}, terms = {}", relation,
Objects.nonNull(newTermHeaders) ? newTermHeaders.size() : "none"); Objects.nonNull(newTermHeaders) ? newTermHeaders.size() : "none");
} }
createTermRelationships(existing, relation, newTermHeaders.values()); createTermRelationships(storeObject, relation, newTermHeaders.values());
continue; continue;
} }
...@@ -230,7 +258,7 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -230,7 +258,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
.filter(t -> !newTermHeaders.containsKey(t.getTermGuid())) .filter(t -> !newTermHeaders.containsKey(t.getTermGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
createTermRelationships(existing, relation, toCreate); createTermRelationships(storeObject, relation, toCreate);
updateTermRelationships(relation, toUpdate); updateTermRelationships(relation, toUpdate);
deleteTermRelationships(relation, toDelete); deleteTermRelationships(relation, toDelete);
...@@ -265,33 +293,33 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -265,33 +293,33 @@ public class GlossaryTermUtils extends GlossaryUtils {
return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingTermHeaders.get(header.getTermGuid())); return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingTermHeaders.get(header.getTermGuid()));
} }
private void processAssociatedCategories(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { private void processAssociatedCategories(AtlasGlossaryTerm storeObject, AtlasGlossaryTerm updatedTerm, RelationshipOperation op) throws AtlasBaseException {
Map<String, AtlasTermCategorizationHeader> newCategories = getAssociatedCategories(updatedTerm); Map<String, AtlasTermCategorizationHeader> newCategories = getAssociatedCategories(updatedTerm);
Map<String, AtlasTermCategorizationHeader> existingCategories = getAssociatedCategories(existing); Map<String, AtlasTermCategorizationHeader> existingCategories = getAssociatedCategories(storeObject);
switch (op) { switch (op) {
case CREATE: case CREATE:
if (Objects.nonNull(newCategories)) { if (Objects.nonNull(newCategories)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new term categorization, term = {}, categories = {}", existing.getGuid(), newCategories.size()); LOG.debug("Creating new term categorization, term = {}, categories = {}", storeObject.getGuid(), newCategories.size());
} }
createTermCategorizationRelationships(existing, newCategories.values()); createTermCategorizationRelationships(storeObject, newCategories.values());
} }
break; break;
case UPDATE: case UPDATE:
// If no existing categories are present then create all existing ones // If no existing categories are present then create all existing ones
if (MapUtils.isEmpty(existingCategories)) { if (MapUtils.isEmpty(existingCategories)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating new term categorization, term = {}, categories = {}", existing.getGuid(), LOG.debug("Creating new term categorization, term = {}, categories = {}", storeObject.getGuid(),
Objects.nonNull(newCategories) ? newCategories.size() : "none"); Objects.nonNull(newCategories) ? newCategories.size() : "none");
} }
createTermCategorizationRelationships(existing, newCategories.values()); createTermCategorizationRelationships(storeObject, newCategories.values());
break; break;
} }
// If no new categories are present then delete all existing ones // If no new categories are present then delete all existing ones
if (MapUtils.isEmpty(newCategories)) { if (MapUtils.isEmpty(newCategories)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Deleting term categorization, term = {}, categories = {}", existing.getGuid(), existingCategories.size()); LOG.debug("Deleting term categorization, term = {}, categories = {}", storeObject.getGuid(), existingCategories.size());
} }
deleteCategorizationRelationship(existingCategories.values()); deleteCategorizationRelationship(existingCategories.values());
break; break;
...@@ -302,13 +330,13 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -302,13 +330,13 @@ public class GlossaryTermUtils extends GlossaryUtils {
.stream() .stream()
.filter(c -> !existingCategories.containsKey(c.getCategoryGuid())) .filter(c -> !existingCategories.containsKey(c.getCategoryGuid()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
createTermCategorizationRelationships(existing, toCreate); createTermCategorizationRelationships(storeObject, toCreate);
Set<AtlasTermCategorizationHeader> toUpdate = newCategories Set<AtlasTermCategorizationHeader> toUpdate = newCategories
.values() .values()
.stream() .stream()
.filter(c -> updatedExistingCategorizationRelation(existingCategories, c)) .filter(c -> updatedExistingCategorizationRelation(existingCategories, c))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
updateTermCategorizationRelationships(existing, toUpdate); updateTermCategorizationRelationships(storeObject, toUpdate);
Set<AtlasTermCategorizationHeader> toDelete = existingCategories Set<AtlasTermCategorizationHeader> toDelete = existingCategories
.values() .values()
.stream() .stream()
...@@ -326,7 +354,7 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -326,7 +354,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingCategories.get(header.getCategoryGuid())); return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingCategories.get(header.getCategoryGuid()));
} }
private Map<String, AtlasTermCategorizationHeader> getAssociatedCategories(final AtlasGlossaryTerm term) { private Map<String, AtlasTermCategorizationHeader> getAssociatedCategories(AtlasGlossaryTerm term) {
if (Objects.nonNull(term.getCategories())) { if (Objects.nonNull(term.getCategories())) {
Map<String, AtlasTermCategorizationHeader> map = new HashMap<>(); Map<String, AtlasTermCategorizationHeader> map = new HashMap<>();
for (AtlasTermCategorizationHeader c : term.getCategories()) { for (AtlasTermCategorizationHeader c : term.getCategories()) {
...@@ -341,9 +369,9 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -341,9 +369,9 @@ public class GlossaryTermUtils extends GlossaryUtils {
} }
} }
private void createTermCategorizationRelationships(AtlasGlossaryTerm existing, Collection<AtlasTermCategorizationHeader> categories) throws AtlasBaseException { private void createTermCategorizationRelationships(AtlasGlossaryTerm storeObject, Collection<AtlasTermCategorizationHeader> categories) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(categories)) { if (CollectionUtils.isNotEmpty(categories)) {
Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories(); Set<AtlasTermCategorizationHeader> existingCategories = storeObject.getCategories();
for (AtlasTermCategorizationHeader categorizationHeader : categories) { for (AtlasTermCategorizationHeader categorizationHeader : categories) {
if (Objects.nonNull(existingCategories) && existingCategories.contains(categorizationHeader)) { if (Objects.nonNull(existingCategories) && existingCategories.contains(categorizationHeader)) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
...@@ -352,18 +380,18 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -352,18 +380,18 @@ public class GlossaryTermUtils extends GlossaryUtils {
continue; continue;
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Creating relation between term = {} and category = {}", existing.getGuid(), categorizationHeader.getDisplayText()); LOG.debug("Creating relation between term = {} and category = {}", storeObject.getGuid(), categorizationHeader.getDisplayText());
} }
createRelationship(defineCategorizedTerm(categorizationHeader, existing.getGuid())); createRelationship(defineCategorizedTerm(categorizationHeader, storeObject.getGuid()));
} }
} }
} }
private void updateTermCategorizationRelationships(AtlasGlossaryTerm existing, Collection<AtlasTermCategorizationHeader> toUpdate) throws AtlasBaseException { private void updateTermCategorizationRelationships(AtlasGlossaryTerm storeObject, Collection<AtlasTermCategorizationHeader> toUpdate) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(toUpdate)) { if (CollectionUtils.isNotEmpty(toUpdate)) {
for (AtlasTermCategorizationHeader categorizationHeader : toUpdate) { for (AtlasTermCategorizationHeader categorizationHeader : toUpdate) {
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("Updating relation between term = {} and category = {}", existing.getGuid(), categorizationHeader.getDisplayText()); LOG.debug("Updating relation between term = {} and category = {}", storeObject.getGuid(), categorizationHeader.getDisplayText());
} }
AtlasRelationship relationship = relationshipStore.getById(categorizationHeader.getRelationGuid()); AtlasRelationship relationship = relationshipStore.getById(categorizationHeader.getRelationGuid());
updateRelationshipAttributes(relationship, categorizationHeader); updateRelationshipAttributes(relationship, categorizationHeader);
...@@ -383,12 +411,12 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -383,12 +411,12 @@ public class GlossaryTermUtils extends GlossaryUtils {
} }
} }
private void createTermRelationships(AtlasGlossaryTerm existing, AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { private void createTermRelationships(AtlasGlossaryTerm storeObject, AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) { if (CollectionUtils.isNotEmpty(terms)) {
Map<String, AtlasRelatedTermHeader> existingRelations; Map<String, AtlasRelatedTermHeader> existingRelations;
if (Objects.nonNull(existing.getRelatedTerms()) && Objects.nonNull(existing.getRelatedTerms().get(relation))) { if (Objects.nonNull(storeObject.getRelatedTerms()) && Objects.nonNull(storeObject.getRelatedTerms().get(relation))) {
Map<String, AtlasRelatedTermHeader> map = new HashMap<>(); Map<String, AtlasRelatedTermHeader> map = new HashMap<>();
for (AtlasRelatedTermHeader t : existing.getRelatedTerms().get(relation)) { for (AtlasRelatedTermHeader t : storeObject.getRelatedTerms().get(relation)) {
AtlasRelatedTermHeader header = map.get(t.getTermGuid()); AtlasRelatedTermHeader header = map.get(t.getTermGuid());
if (header == null || (StringUtils.isEmpty(header.getRelationGuid()) && StringUtils.isNotEmpty(t.getRelationGuid()))) { if (header == null || (StringUtils.isEmpty(header.getRelationGuid()) && StringUtils.isNotEmpty(t.getRelationGuid()))) {
map.put(t.getTermGuid(), t); map.put(t.getTermGuid(), t);
...@@ -406,7 +434,7 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -406,7 +434,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
continue; continue;
} }
if (existing.getGuid().equals(term.getTermGuid())) { if (storeObject.getGuid().equals(term.getTermGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_TERM_RELATION_TO_SELF); throw new AtlasBaseException(AtlasErrorCode.INVALID_TERM_RELATION_TO_SELF);
} }
...@@ -414,7 +442,7 @@ public class GlossaryTermUtils extends GlossaryUtils { ...@@ -414,7 +442,7 @@ public class GlossaryTermUtils extends GlossaryUtils {
LOG.debug("Creating new term relation = {}, terms = {}", relation, term.getDisplayText()); LOG.debug("Creating new term relation = {}, terms = {}", relation, term.getDisplayText());
} }
createRelationship(defineTermRelation(relation, existing.getGuid(), term)); createRelationship(defineTermRelation(relation, storeObject.getGuid(), term));
} }
} }
} }
......
...@@ -19,6 +19,9 @@ package org.apache.atlas.glossary; ...@@ -19,6 +19,9 @@ package org.apache.atlas.glossary;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.glossary.AtlasGlossary;
import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.instance.AtlasRelationship; import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.repository.ogm.DataAccess; import org.apache.atlas.repository.ogm.DataAccess;
...@@ -64,6 +67,26 @@ public abstract class GlossaryUtils { ...@@ -64,6 +67,26 @@ public abstract class GlossaryUtils {
this.dataAccess = dataAccess; this.dataAccess = dataAccess;
} }
public static AtlasGlossary getGlossarySkeleton(String glossaryGuid) {
AtlasGlossary glossary = new AtlasGlossary();
glossary.setGuid(glossaryGuid);
return glossary;
}
public static AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String termGuid) {
AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
glossaryTerm.setGuid(termGuid);
return glossaryTerm;
}
public static AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final String categoryGuid) {
AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
glossaryCategory.setGuid(categoryGuid);
return glossaryCategory;
}
protected void createRelationship(AtlasRelationship relationship) throws AtlasBaseException { protected void createRelationship(AtlasRelationship relationship) throws AtlasBaseException {
try { try {
relationshipStore.create(relationship); relationshipStore.create(relationship);
......
...@@ -314,7 +314,12 @@ public class GlossaryServiceTest { ...@@ -314,7 +314,12 @@ public class GlossaryServiceTest {
List<AtlasGlossaryCategory> categories = glossaryService.createCategories(Arrays.asList(accountCategory, mortgageCategory)); List<AtlasGlossaryCategory> categories = glossaryService.createCategories(Arrays.asList(accountCategory, mortgageCategory));
accountCategory.setGuid(categories.get(0).getGuid()); accountCategory.setGuid(categories.get(0).getGuid());
assertNotNull(accountCategory.getParentCategory());
assertEquals(accountCategory.getParentCategory().getCategoryGuid(), customerCategory.getGuid());
assertTrue(accountCategory.getQualifiedName().endsWith(customerCategory.getQualifiedName()));
mortgageCategory.setGuid(categories.get(1).getGuid()); mortgageCategory.setGuid(categories.get(1).getGuid());
assertNull(mortgageCategory.getParentCategory());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Category creation should've succeeded", e); fail("Category creation should've succeeded", e);
} }
...@@ -395,11 +400,51 @@ public class GlossaryServiceTest { ...@@ -395,11 +400,51 @@ public class GlossaryServiceTest {
public void testDeleteGlossary() { public void testDeleteGlossary() {
try { try {
glossaryService.deleteGlossary(bankGlossary.getGuid()); glossaryService.deleteGlossary(bankGlossary.getGuid());
// Fetch deleted glossary
try { try {
glossaryService.getGlossary(bankGlossary.getGuid()); glossaryService.getGlossary(bankGlossary.getGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND); assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
} }
// Fetch delete terms
try {
glossaryService.getTerm(fixedRateMortgage.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
try {
glossaryService.getTerm(adjustableRateMortgage.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
try {
glossaryService.getTerm(savingsAccount.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
try {
glossaryService.getTerm(checkingAccount.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
// Fetch deleted categories
try {
glossaryService.getCategory(customerCategory.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
try {
glossaryService.getCategory(accountCategory.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
try {
glossaryService.getCategory(mortgageCategory.getGuid());
} catch (AtlasBaseException e) {
assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Glossary delete should've succeeded", e); fail("Glossary delete should've succeeded", e);
} }
...@@ -460,11 +505,22 @@ public class GlossaryServiceTest { ...@@ -460,11 +505,22 @@ public class GlossaryServiceTest {
// Unlink children // Unlink children
try { try {
AtlasGlossaryCategory category = glossaryService.getCategory(customerCategory.getGuid()); customerCategory = glossaryService.getCategory(customerCategory.getGuid());
category.setChildrenCategories(null); customerCategory.setChildrenCategories(null);
category = glossaryService.updateCategory(category); customerCategory = glossaryService.updateCategory(customerCategory);
assertNotNull(category); assertNotNull(customerCategory);
assertNull(category.getChildrenCategories()); assertNull(customerCategory.getChildrenCategories());
accountCategory = glossaryService.getCategory(accountCategory.getGuid());
assertNull(accountCategory.getParentCategory());
assertTrue(accountCategory.getQualifiedName().endsWith(bankGlossary.getQualifiedName()));
mortgageCategory = glossaryService.getCategory(mortgageCategory.getGuid());
assertNull(mortgageCategory.getParentCategory());
assertTrue(mortgageCategory.getQualifiedName().endsWith(bankGlossary.getQualifiedName()));
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Customer category fetch should've succeeded"); fail("Customer category fetch should've succeeded");
} }
...@@ -519,16 +575,27 @@ public class GlossaryServiceTest { ...@@ -519,16 +575,27 @@ public class GlossaryServiceTest {
try { try {
customerCategory = glossaryService.getCategory(customerCategory.getGuid()); customerCategory = glossaryService.getCategory(customerCategory.getGuid());
mortgageCategory = glossaryService.getCategory(mortgageCategory.getGuid());
accountCategory = glossaryService.getCategory(accountCategory.getGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Category fetch for migration should've succeeded"); fail("Category fetch for migration should've succeeded");
} }
customerCategory.setAnchor(newGlossaryHeader); customerCategory.setAnchor(newGlossaryHeader);
customerCategory.setChildrenCategories(null); mortgageCategory.setAnchor(newGlossaryHeader);
accountCategory.setAnchor(newGlossaryHeader);
try { try {
customerCategory = glossaryService.updateCategory(customerCategory); customerCategory = glossaryService.updateCategory(customerCategory);
assertTrue(CollectionUtils.isEmpty(customerCategory.getChildrenCategories())); mortgageCategory = glossaryService.updateCategory(mortgageCategory);
accountCategory = glossaryService.updateCategory(accountCategory);
assertTrue(customerCategory.getQualifiedName().endsWith(creditUnionGlossary.getQualifiedName()));
assertEquals(customerCategory.getAnchor().getGlossaryGuid(), newGlossaryHeader.getGlossaryGuid());
assertTrue(accountCategory.getQualifiedName().endsWith(creditUnionGlossary.getQualifiedName()));
assertEquals(accountCategory.getAnchor().getGlossaryGuid(), newGlossaryHeader.getGlossaryGuid());
assertTrue(mortgageCategory.getQualifiedName().endsWith(creditUnionGlossary.getQualifiedName()));
assertEquals(mortgageCategory.getAnchor().getGlossaryGuid(), newGlossaryHeader.getGlossaryGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Category anchor change should've succeeded"); fail("Category anchor change should've succeeded");
} }
...@@ -536,10 +603,50 @@ public class GlossaryServiceTest { ...@@ -536,10 +603,50 @@ public class GlossaryServiceTest {
try { try {
List<AtlasRelatedCategoryHeader> categories = glossaryService.getGlossaryCategoriesHeaders(creditUnionGlossary.getGuid(), 0, 5, SortOrder.ASCENDING); List<AtlasRelatedCategoryHeader> categories = glossaryService.getGlossaryCategoriesHeaders(creditUnionGlossary.getGuid(), 0, 5, SortOrder.ASCENDING);
assertNotNull(categories); assertNotNull(categories);
assertEquals(categories.size(), 1); assertEquals(categories.size(), 3);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Category migration should've succeeded", e); fail("Category migration should've succeeded", e);
} }
// Move the entire hierarchy back to the original glossary
AtlasRelatedCategoryHeader child1 = new AtlasRelatedCategoryHeader();
child1.setCategoryGuid(accountCategory.getGuid());
AtlasRelatedCategoryHeader child2 = new AtlasRelatedCategoryHeader();
child2.setCategoryGuid(mortgageCategory.getGuid());
customerCategory.addChild(child1);
customerCategory.addChild(child2);
try {
customerCategory = glossaryService.updateCategory(customerCategory);
assertTrue(CollectionUtils.isNotEmpty(customerCategory.getChildrenCategories()));
} catch (AtlasBaseException e) {
fail("Children addition to Category should've succeeded");
}
customerCategory.setAnchor(newGlossaryHeader);
newGlossaryHeader.setGlossaryGuid(bankGlossary.getGuid());
try {
customerCategory = glossaryService.getCategory(customerCategory.getGuid());
assertTrue(CollectionUtils.isNotEmpty(customerCategory.getChildrenCategories()));
} catch (AtlasBaseException e) {
fail("Category fetch should've succeeded");
}
try {
accountCategory = glossaryService.getCategory(accountCategory.getGuid());
assertEquals(accountCategory.getAnchor().getGlossaryGuid(), customerCategory.getAnchor().getGlossaryGuid());
} catch (AtlasBaseException e) {
fail("Category fetch should've succeeded");
}
try {
mortgageCategory = glossaryService.getCategory(mortgageCategory.getGuid());
assertEquals(mortgageCategory.getAnchor().getGlossaryGuid(), customerCategory.getAnchor().getGlossaryGuid());
} catch (AtlasBaseException e) {
fail("Category fetch should've succeeded");
}
} }
@Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
...@@ -689,6 +796,12 @@ public class GlossaryServiceTest { ...@@ -689,6 +796,12 @@ public class GlossaryServiceTest {
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Term update should've succeeded", e); fail("Term update should've succeeded", e);
} }
try {
entityStore.deleteById(relatedObjectId.getGuid());
} catch (AtlasBaseException e) {
fail("Entity delete should've succeeded");
}
} }
@Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
......
...@@ -394,7 +394,7 @@ public class GlossaryREST { ...@@ -394,7 +394,7 @@ public class GlossaryREST {
try { try {
glossary.setAttribute(entry.getKey(), entry.getValue()); glossary.setAttribute(entry.getKey(), entry.getValue());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARTIAL_UPDATE_ATTR, "Glossary", entry.getKey()); throw new AtlasBaseException(AtlasErrorCode.INVALID_PARTIAL_UPDATE_ATTR, entry.getKey(), "Glossary");
} }
} }
return glossaryService.updateGlossary(glossary); return glossaryService.updateGlossary(glossary);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment