Repository: atlas Updated Branches: refs/heads/master 4a938d873 -> cabc1e550
ATLAS-2534: Glossary REST API (bugfix) Change-Id: Ic0b40d722f2a797db19dd7ee95ef30866e073128 Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/cabc1e55 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/cabc1e55 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/cabc1e55 Branch: refs/heads/master Commit: cabc1e55059b70cfab49e1ca960d2cdee6a3828f Parents: 4a938d8 Author: apoorvnaik <apoorvn...@apache.org> Authored: Mon Apr 16 14:02:31 2018 -0700 Committer: apoorvnaik <apoorvn...@apache.org> Committed: Wed Apr 18 07:54:58 2018 -0700 ---------------------------------------------------------------------- .../java/org/apache/atlas/AtlasErrorCode.java | 3 + .../atlas/glossary/GlossaryCategoryUtils.java | 98 ++++++++---- .../apache/atlas/glossary/GlossaryService.java | 49 +++++- .../atlas/glossary/GlossaryTermUtils.java | 95 ++++++++---- .../apache/atlas/glossary/GlossaryUtils.java | 7 +- .../store/graph/v1/EntityGraphRetriever.java | 8 +- .../atlas/glossary/GlossaryServiceTest.java | 153 +++++++++++-------- .../org/apache/atlas/web/rest/GlossaryREST.java | 3 + 8 files changed, 278 insertions(+), 138 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index bbb1b1a..3efe41c 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -168,6 +168,9 @@ public enum AtlasErrorCode { RELATIONSHIP_ALREADY_EXISTS(409, "ATLAS-409-00-004", "relationship {0} already exists between entities {1} and {2}"), TYPE_HAS_RELATIONSHIPS(409, "ATLAS-409-00-005", "Given type {0} has associated relationshipDefs"), SAVED_SEARCH_ALREADY_EXISTS(409, "ATLAS-409-00-006", "search named {0} already exists for user {1}"), + GLOSSARY_ALREADY_EXISTS(409, "ATLAS-409-00-007", "Glossary with qualifiedName {0} already exists"), + GLOSSARY_TERM_ALREADY_EXISTS(409, "ATLAS-409-00-009", "Glossary term with qualifiedName {0} already exists"), + GLOSSARY_CATEGORY_ALREADY_EXISTS(409, "ATLAS-409-00-00A", "Glossary category with qualifiedName {0} already exists"), // All internal errors go here INTERNAL_ERROR(500, "ATLAS-500-00-001", "Internal server error {0}"), http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java b/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java index 46d8889..1423b98 100644 --- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryCategoryUtils.java @@ -29,9 +29,13 @@ import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -96,8 +100,8 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void processParentCategory(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { - AtlasRelatedCategoryHeader newParent = newObj.getParentCategory(); + private void processParentCategory(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { + AtlasRelatedCategoryHeader newParent = updatedCategory.getParentCategory(); AtlasRelatedCategoryHeader existingParent = existing.getParentCategory(); switch (op) { case CREATE: @@ -152,9 +156,9 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void processAssociatedTerms(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { - Set<AtlasRelatedTermHeader> newTerms = newObj.getTerms(); - Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms(); + private void processAssociatedTerms(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { + Map<String, AtlasRelatedTermHeader> newTerms = getTerms(updatedCategory); + Map<String, AtlasRelatedTermHeader> existingTerms = getTerms(existing); switch (op) { case CREATE: @@ -162,51 +166,66 @@ public class GlossaryCategoryUtils extends GlossaryUtils { LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), Objects.nonNull(newTerms) ? newTerms.size() : "none"); } - createTermCategorizationRelationships(existing, newTerms); + createTermCategorizationRelationships(existing, newTerms.values()); break; case UPDATE: - if (CollectionUtils.isEmpty(existingTerms)) { + if (MapUtils.isEmpty(existingTerms)) { if (DEBUG_ENABLED) { LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), Objects.nonNull(newTerms) ? newTerms.size() : "none"); } - createTermCategorizationRelationships(existing, newTerms); + createTermCategorizationRelationships(existing, newTerms.values()); break; } - if (CollectionUtils.isEmpty(newTerms)) { + if (MapUtils.isEmpty(newTerms)) { if (DEBUG_ENABLED) { LOG.debug("Deleting term relation with category = {}, terms = {}", existing.getDisplayName(), existingTerms.size()); } - deleteTermCategorizationRelationships(existing, existingTerms); + deleteTermCategorizationRelationships(existing, existingTerms.values()); break; } Set<AtlasRelatedTermHeader> toCreate = newTerms + .values() .stream() - .filter(c -> Objects.isNull(c.getRelationGuid())) + .filter(t -> !existingTerms.containsKey(t.getTermGuid())) .collect(Collectors.toSet()); createTermCategorizationRelationships(existing, toCreate); Set<AtlasRelatedTermHeader> toUpdate = newTerms + .values() .stream() - .filter(c -> Objects.nonNull(c.getRelationGuid()) && existingTerms.contains(c)) + .filter(t -> updatedExistingTermRelation(existingTerms, t)) .collect(Collectors.toSet()); updateTermCategorizationRelationships(existing, toUpdate); Set<AtlasRelatedTermHeader> toDelete = existingTerms + .values() .stream() - .filter(c -> !toCreate.contains(c) && !toUpdate.contains(c)) + .filter(t -> !newTerms.containsKey(t.getTermGuid())) .collect(Collectors.toSet()); deleteTermCategorizationRelationships(existing, toDelete); break; case DELETE: - deleteTermCategorizationRelationships(existing, existingTerms); + deleteTermCategorizationRelationships(existing, existingTerms.values()); break; } } - private void createTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private boolean updatedExistingTermRelation(Map<String, AtlasRelatedTermHeader> existingTerms, AtlasRelatedTermHeader term) { + return Objects.nonNull(term.getRelationGuid()) && !existingTerms.get(term.getTermGuid()).equals(term); + } + + private Map<String, AtlasRelatedTermHeader> getTerms(final AtlasGlossaryCategory category) { + return Objects.nonNull(category.getTerms()) ? + category.getTerms() + .stream() + .collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid, t -> t)) : + Collections.EMPTY_MAP; + } + + private void createTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms(); for (AtlasRelatedTermHeader term : terms) { @@ -228,7 +247,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void updateTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private void updateTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { for (AtlasRelatedTermHeader term : terms) { if (DEBUG_ENABLED) { @@ -241,7 +260,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void deleteTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private void deleteTermCategorizationRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { for (AtlasRelatedTermHeader term : terms) { if (DEBUG_ENABLED) { @@ -252,61 +271,76 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void processCategoryChildren(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { - Set<AtlasRelatedCategoryHeader> newChildren = newObj.getChildrenCategories(); - Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories(); + private void processCategoryChildren(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException { + Map<String, AtlasRelatedCategoryHeader> newChildren = getChildren(updatedCategory); + Map<String, AtlasRelatedCategoryHeader> existingChildren = getChildren(existing); switch (op) { case CREATE: if (DEBUG_ENABLED) { LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(), Objects.nonNull(newChildren) ? newChildren.size() : "none"); } - createCategoryRelationships(existing, newChildren); + createCategoryRelationships(existing, newChildren.values()); break; case UPDATE: // Create new children - if (CollectionUtils.isEmpty(existingChildren)) { + if (MapUtils.isEmpty(existingChildren)) { if (DEBUG_ENABLED) { LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(), Objects.nonNull(newChildren) ? newChildren.size() : "none"); } - createCategoryRelationships(existing, newChildren); + createCategoryRelationships(existing, newChildren.values()); break; } // Delete current children - if (CollectionUtils.isEmpty(newChildren)) { + if (MapUtils.isEmpty(newChildren)) { if (DEBUG_ENABLED) { LOG.debug("Deleting children, category = {}, children = {}", existing.getDisplayName(), existingChildren.size()); } - deleteCategoryRelationships(existing, existingChildren); + deleteCategoryRelationships(existing, existingChildren.values()); break; } Set<AtlasRelatedCategoryHeader> toCreate = newChildren + .values() .stream() - .filter(c -> Objects.isNull(c.getRelationGuid())) + .filter(c -> !existingChildren.containsKey(c.getCategoryGuid())) .collect(Collectors.toSet()); createCategoryRelationships(existing, toCreate); Set<AtlasRelatedCategoryHeader> toUpdate = newChildren + .values() .stream() - .filter(c -> Objects.nonNull(c.getRelationGuid()) && existingChildren.contains(c)) + .filter(c -> updatedExistingCategoryRelation(existingChildren, c)) .collect(Collectors.toSet()); updateCategoryRelationships(existing, toUpdate); Set<AtlasRelatedCategoryHeader> toDelete = existingChildren + .values() .stream() - .filter(c -> !toCreate.contains(c) && !toUpdate.contains(c)) + .filter(c -> !newChildren.containsKey(c.getCategoryGuid())) .collect(Collectors.toSet()); deleteCategoryRelationships(existing, toDelete); break; case DELETE: - deleteCategoryRelationships(existing, existingChildren); + deleteCategoryRelationships(existing, existingChildren.values()); break; } } - private void createCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException { + private boolean updatedExistingCategoryRelation(Map<String, AtlasRelatedCategoryHeader> existingChildren, AtlasRelatedCategoryHeader header) { + return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingChildren.get(header.getCategoryGuid())); + } + + private Map<String, AtlasRelatedCategoryHeader> getChildren(final AtlasGlossaryCategory category) { + return Objects.nonNull(category.getChildrenCategories()) ? + category.getChildrenCategories() + .stream() + .collect(Collectors.toMap(AtlasRelatedCategoryHeader::getCategoryGuid, c -> c)) : + Collections.EMPTY_MAP; + } + + private void createCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(newChildren)) { Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories(); for (AtlasRelatedCategoryHeader child : newChildren) { @@ -324,7 +358,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void updateCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException { + private void updateCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(toUpdate)) { for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) { if (DEBUG_ENABLED) { @@ -337,7 +371,7 @@ public class GlossaryCategoryUtils extends GlossaryUtils { } } - private void deleteCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException { + private void deleteCategoryRelationships(AtlasGlossaryCategory existing, Collection<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(existingChildren)) { for (AtlasRelatedCategoryHeader child : existingChildren) { if (DEBUG_ENABLED) { http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java index 9fd795b..5db0bb0 100644 --- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java @@ -27,6 +27,7 @@ import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader; import org.apache.atlas.model.instance.AtlasRelatedObjectId; +import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.ogm.DataAccess; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1; @@ -53,13 +54,17 @@ public class GlossaryService { private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class); private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled(); - private final DataAccess dataAccess; - private final GlossaryTermUtils glossaryTermUtils; - private final GlossaryCategoryUtils glossaryCategoryUtils; + private static final String QUALIFIED_NAME_ATTR = "qualifiedName"; + + private final DataAccess dataAccess; + private final GlossaryTermUtils glossaryTermUtils; + private final GlossaryCategoryUtils glossaryCategoryUtils; + private final AtlasTypeRegistry atlasTypeRegistry; @Inject public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore relationshipStore, final AtlasTypeRegistry typeRegistry) { this.dataAccess = dataAccess; + this.atlasTypeRegistry = typeRegistry; glossaryTermUtils = new GlossaryTermUtils(relationshipStore, typeRegistry); glossaryCategoryUtils = new GlossaryCategoryUtils(relationshipStore, typeRegistry); } @@ -78,7 +83,7 @@ public class GlossaryService { LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, offset, sortOrder); } - List<String> glossaryGuids = AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_PREFIX, sortOrder); + List<String> glossaryGuids = AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME, sortOrder); PaginationHelper paginationHelper = new PaginationHelper<>(glossaryGuids, offset, limit); List<AtlasGlossary> ret; @@ -118,6 +123,7 @@ public class GlossaryService { if (Objects.isNull(atlasGlossary)) { throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary definition missing"); } + if (StringUtils.isEmpty(atlasGlossary.getQualifiedName())) { if (StringUtils.isEmpty(atlasGlossary.getDisplayName())) { throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED); @@ -125,11 +131,17 @@ public class GlossaryService { atlasGlossary.setQualifiedName(atlasGlossary.getDisplayName()); } } + + if (glossaryExists(atlasGlossary)) { + throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_ALREADY_EXISTS, atlasGlossary.getQualifiedName()); + } + AtlasGlossary saved = dataAccess.save(atlasGlossary); if (DEBUG_ENABLED) { LOG.debug("<== GlossaryService.createGlossary() : {}", saved); } + return saved; } @@ -297,6 +309,10 @@ public class GlossaryService { } } + if (termExists(glossaryTerm)) { + throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_ALREADY_EXISTS, glossaryTerm.getQualifiedName()); + } + AtlasGlossaryTerm existing = dataAccess.save(glossaryTerm); glossaryTermUtils.processTermRelations(glossaryTerm, existing, GlossaryUtils.RelationshipOperation.CREATE); @@ -457,6 +473,10 @@ public class GlossaryService { } } + if (categoryExists(glossaryCategory)) { + throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_ALREADY_EXISTS, glossaryCategory.getQualifiedName()); + } + AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory); // Attempt relation creation @@ -726,6 +746,27 @@ public class GlossaryService { return glossary; } + private boolean glossaryExists(AtlasGlossary atlasGlossary) { + AtlasVertex vertex = AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TYPENAME), new HashMap<String, Object>() {{ + put(QUALIFIED_NAME_ATTR, atlasGlossary.getQualifiedName()); + }}); + return Objects.nonNull(vertex); + } + + private boolean termExists(AtlasGlossaryTerm term) { + AtlasVertex vertex = AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_TERM_TYPENAME), new HashMap<String, Object>() {{ + put(QUALIFIED_NAME_ATTR, term.getQualifiedName()); + }}); + return Objects.nonNull(vertex); + } + + private boolean categoryExists(AtlasGlossaryCategory category) { + AtlasVertex vertex = AtlasGraphUtilsV1.findByUniqueAttributes(atlasTypeRegistry.getEntityTypeByName(GlossaryUtils.ATLAS_GLOSSARY_CATEGORY_TYPENAME), new HashMap<String, Object>() {{ + put(QUALIFIED_NAME_ATTR, category.getQualifiedName()); + }}); + return Objects.nonNull(vertex); + } + private void deleteCategories(final AtlasGlossary existing, final Set<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(categories)) { if (DEBUG_ENABLED) { http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java b/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java index c2d2d2b..803fad6 100644 --- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java @@ -31,10 +31,12 @@ import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -170,39 +172,42 @@ public class GlossaryTermUtils extends GlossaryUtils { break; case UPDATE: for (AtlasGlossaryTerm.Relation relation : AtlasGlossaryTerm.Relation.values()) { - Set<AtlasRelatedTermHeader> existingTermHeaders = existingRelatedTerms.get(relation); - Set<AtlasRelatedTermHeader> newTermHeaders = newRelatedTerms.get(relation); + Map<String, AtlasRelatedTermHeader> existingTermHeaders = getRelatedTermHeaders(existingRelatedTerms, relation); + Map<String, AtlasRelatedTermHeader> newTermHeaders = getRelatedTermHeaders(newRelatedTerms, relation); // No existing term relations, create all - if (CollectionUtils.isEmpty(existingTermHeaders)) { + if (MapUtils.isEmpty(existingTermHeaders)) { if (DEBUG_ENABLED) { LOG.debug("Creating new term relations, relation = {}, terms = {}", relation, Objects.nonNull(newTermHeaders) ? newTermHeaders.size() : "none"); } - createTermRelationships(existing, relation, newTermHeaders); + createTermRelationships(existing, relation, newTermHeaders.values()); continue; } // Existing term relations but nothing in updated object, remove all - if (CollectionUtils.isEmpty(newTermHeaders)) { + if (MapUtils.isEmpty(newTermHeaders)) { if (DEBUG_ENABLED) { LOG.debug("Deleting existing term relations, relation = {}, terms = {}", relation, existingTermHeaders.size()); } - deleteTermRelationships(relation, existingTermHeaders); + deleteTermRelationships(relation, existingTermHeaders.values()); continue; } // Determine what to update, delete or create Set<AtlasRelatedTermHeader> toCreate = newTermHeaders + .values() .stream() - .filter(t -> Objects.isNull(t.getRelationGuid())) + .filter(t -> !existingTermHeaders.containsKey(t.getTermGuid())) .collect(Collectors.toSet()); Set<AtlasRelatedTermHeader> toUpdate = newTermHeaders + .values() .stream() - .filter(t -> Objects.nonNull(t.getRelationGuid()) && existingTermHeaders.contains(t)) + .filter(t -> updatedExistingTermRelation(existingTermHeaders, t)) .collect(Collectors.toSet()); Set<AtlasRelatedTermHeader> toDelete = existingTermHeaders + .values() .stream() - .filter(t -> !toCreate.contains(t) && !toUpdate.contains(t)) + .filter(t -> !newTermHeaders.containsKey(t.getTermGuid())) .collect(Collectors.toSet()); createTermRelationships(existing, relation, toCreate); @@ -221,61 +226,88 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void processAssociatedCategories(AtlasGlossaryTerm newObj, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { - Set<AtlasTermCategorizationHeader> newCategories = newObj.getCategories(); - Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories(); + private Map<String, AtlasRelatedTermHeader> getRelatedTermHeaders(Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> relatedTerms, AtlasGlossaryTerm.Relation relation) { + return Objects.nonNull(relatedTerms.get(relation)) ? + relatedTerms.get(relation) + .stream() + .collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid, t -> t)) : + Collections.EMPTY_MAP; + } + + private boolean updatedExistingTermRelation(Map<String, AtlasRelatedTermHeader> existingTermHeaders, AtlasRelatedTermHeader header) { + return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingTermHeaders.get(header.getTermGuid())); + } + + private void processAssociatedCategories(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { + Map<String, AtlasTermCategorizationHeader> newCategories = getAssociatedCategories(updatedTerm); + Map<String, AtlasTermCategorizationHeader> existingCategories = getAssociatedCategories(existing); switch (op) { case CREATE: if (Objects.nonNull(newCategories)) { if (DEBUG_ENABLED) { LOG.debug("Creating new term categorization, term = {}, categories = {}", existing.getGuid(), newCategories.size()); } - createTermCategorizationRelationships(existing, newCategories); + createTermCategorizationRelationships(existing, newCategories.values()); } break; case UPDATE: // If no existing categories are present then create all existing ones - if (CollectionUtils.isEmpty(existingCategories)) { + if (MapUtils.isEmpty(existingCategories)) { if (DEBUG_ENABLED) { LOG.debug("Creating new term categorization, term = {}, categories = {}", existing.getGuid(), Objects.nonNull(newCategories) ? newCategories.size() : "none"); } - createTermCategorizationRelationships(existing, newCategories); + createTermCategorizationRelationships(existing, newCategories.values()); break; } // If no new categories are present then delete all existing ones - if (CollectionUtils.isEmpty(newCategories)) { + if (MapUtils.isEmpty(newCategories)) { if (DEBUG_ENABLED) { LOG.debug("Deleting term categorization, term = {}, categories = {}", existing.getGuid(), existingCategories.size()); } - deleteCategorizationRelationship(existingCategories); + deleteCategorizationRelationship(existingCategories.values()); break; } Set<AtlasTermCategorizationHeader> toCreate = newCategories + .values() .stream() - .filter(c -> Objects.isNull(c.getRelationGuid())) + .filter(c -> !existingCategories.containsKey(c.getCategoryGuid())) .collect(Collectors.toSet()); createTermCategorizationRelationships(existing, toCreate); Set<AtlasTermCategorizationHeader> toUpdate = newCategories + .values() .stream() - .filter(c -> Objects.nonNull(c.getRelationGuid()) && existingCategories.contains(c)) + .filter(c -> updatedExistingCategorizationRelation(existingCategories, c)) .collect(Collectors.toSet()); updateTermCategorizationRelationships(existing, toUpdate); Set<AtlasTermCategorizationHeader> toDelete = existingCategories + .values() .stream() - .filter(c -> !toCreate.contains(c) && !toUpdate.contains(c)) + .filter(c -> !newCategories.containsKey(c.getCategoryGuid())) .collect(Collectors.toSet()); deleteCategorizationRelationship(toDelete); break; case DELETE: - deleteCategorizationRelationship(existingCategories); + deleteCategorizationRelationship(existingCategories.values()); break; } } - private void createTermCategorizationRelationships(AtlasGlossaryTerm existing, Set<AtlasTermCategorizationHeader> categories) throws AtlasBaseException { + private boolean updatedExistingCategorizationRelation(Map<String, AtlasTermCategorizationHeader> existingCategories, AtlasTermCategorizationHeader header) { + return Objects.nonNull(header.getRelationGuid()) && !header.equals(existingCategories.get(header.getCategoryGuid())); + } + + private Map<String, AtlasTermCategorizationHeader> getAssociatedCategories(final AtlasGlossaryTerm term) { + return Objects.nonNull(term.getCategories()) ? + term.getCategories() + .stream() + .collect(Collectors.toMap(AtlasTermCategorizationHeader::getCategoryGuid, c -> c)) : + Collections.EMPTY_MAP; + } + + private void createTermCategorizationRelationships(AtlasGlossaryTerm existing, Collection<AtlasTermCategorizationHeader> categories) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(categories)) { Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories(); for (AtlasTermCategorizationHeader categorizationHeader : categories) { @@ -293,7 +325,7 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void updateTermCategorizationRelationships(AtlasGlossaryTerm existing, Set<AtlasTermCategorizationHeader> toUpdate) throws AtlasBaseException { + private void updateTermCategorizationRelationships(AtlasGlossaryTerm existing, Collection<AtlasTermCategorizationHeader> toUpdate) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(toUpdate)) { for (AtlasTermCategorizationHeader categorizationHeader : toUpdate) { if (DEBUG_ENABLED) { @@ -306,7 +338,7 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void deleteCategorizationRelationship(Set<AtlasTermCategorizationHeader> existingCategories) throws AtlasBaseException { + private void deleteCategorizationRelationship(Collection<AtlasTermCategorizationHeader> existingCategories) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(existingCategories)) { for (AtlasTermCategorizationHeader categorizationHeader : existingCategories) { if (DEBUG_ENABLED) { @@ -317,11 +349,16 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void createTermRelationships(AtlasGlossaryTerm existing, AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private void createTermRelationships(AtlasGlossaryTerm existing, AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { - Set<AtlasRelatedTermHeader> existingRelations = existing.getRelatedTerms().get(relation); + Map<String, AtlasRelatedTermHeader> existingRelations; + if (Objects.nonNull(existing.getRelatedTerms()) && Objects.nonNull(existing.getRelatedTerms().get(relation))) { + existingRelations = existing.getRelatedTerms().get(relation).stream().collect(Collectors.toMap(AtlasRelatedTermHeader::getTermGuid, t -> t)); + } else { + existingRelations = Collections.EMPTY_MAP; + } for (AtlasRelatedTermHeader term : terms) { - if (Objects.nonNull(existingRelations) && existingRelations.contains(term)) { + if (Objects.nonNull(existingRelations) && existingRelations.containsKey(term.getTermGuid())) { if (DEBUG_ENABLED) { LOG.debug("Skipping existing term relation termGuid={}", term.getTermGuid()); } @@ -335,7 +372,7 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void updateTermRelationships(AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private void updateTermRelationships(AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { for (AtlasRelatedTermHeader term : terms) { if (DEBUG_ENABLED) { @@ -348,7 +385,7 @@ public class GlossaryTermUtils extends GlossaryUtils { } } - private void deleteTermRelationships(AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + private void deleteTermRelationships(AtlasGlossaryTerm.Relation relation, Collection<AtlasRelatedTermHeader> terms) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(terms)) { for (AtlasRelatedTermHeader termHeader : terms) { if (DEBUG_ENABLED) { http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java b/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java index 38555cc..ec8a1dc 100644 --- a/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java @@ -36,8 +36,12 @@ public abstract class GlossaryUtils { public static final String TERM_ASSIGNMENT_ATTR_STEWARD = "steward"; public static final String TERM_ASSIGNMENT_ATTR_SOURCE = "source"; - static final String ATLAS_GLOSSARY_PREFIX = "__AtlasGlossary"; + static final String ATLAS_GLOSSARY_TYPENAME = "__AtlasGlossary"; + static final String ATLAS_GLOSSARY_TERM_TYPENAME = "__AtlasGlossaryTerm"; + static final String ATLAS_GLOSSARY_CATEGORY_TYPENAME = "__AtlasGlossaryCategory"; + // Relation name constants + protected static final String ATLAS_GLOSSARY_PREFIX = ATLAS_GLOSSARY_TYPENAME; protected static final String TERM_ANCHOR = ATLAS_GLOSSARY_PREFIX + "TermAnchor"; protected static final String CATEGORY_ANCHOR = ATLAS_GLOSSARY_PREFIX + "CategoryAnchor"; protected static final String CATEGORY_HIERARCHY = ATLAS_GLOSSARY_PREFIX + "CategoryHierarchyLink"; @@ -49,7 +53,6 @@ public abstract class GlossaryUtils { protected static final String TERM_RELATION_ATTR_SOURCE = "source"; protected static final String TERM_RELATION_ATTR_STATUS = "status"; - protected final AtlasRelationshipStore relationshipStore; protected final AtlasTypeRegistry typeRegistry; http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java index 57c9135..23ffdcd 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java @@ -500,12 +500,8 @@ public final class EntityGraphRetriever { Iterable edges = entityVertex.query().direction(AtlasEdgeDirection.IN).label(TERM_ASSIGNMENT_LABEL).edges(); if (edges != null) { - Iterator<AtlasEdge> iterator = edges.iterator(); - - while (iterator.hasNext()) { - AtlasEdge edge = iterator.next(); - - if (edge != null) { + for (final AtlasEdge edge : (Iterable<AtlasEdge>) edges) { + if (edge != null && GraphHelper.getStatus(edge) != AtlasEntity.Status.DELETED) { ret.add(toTermAssignmentHeader(edge)); } } http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java b/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java index 0294550..6deef80 100644 --- a/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java @@ -39,6 +39,7 @@ import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.utils.AtlasJson; +import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.SkipException; @@ -55,10 +56,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; +import static org.testng.Assert.*; @Guice(modules = TestModules.TestOnlyModule.class) public class GlossaryServiceTest { @@ -96,10 +94,8 @@ public class GlossaryServiceTest { } catch (AtlasBaseException | IOException e) { throw new SkipException("SubjectArea model loading failed"); } - } - @Test(groups = "Glossary.CREATE") - public void testCreateGlossary() { + // Glossary bankGlossary = new AtlasGlossary(); bankGlossary.setQualifiedName("testBankingGlossary"); bankGlossary.setDisplayName("Banking glossary"); @@ -116,34 +112,26 @@ public class GlossaryServiceTest { creditUnionGlossary.setUsage("N/A"); creditUnionGlossary.setLanguage("en-US"); - try { - AtlasGlossary created = glossaryService.createGlossary(bankGlossary); - bankGlossary.setGuid(created.getGuid()); - created = glossaryService.createGlossary(creditUnionGlossary); - creditUnionGlossary.setGuid(created.getGuid()); - } catch (AtlasBaseException e) { - fail("Glossary creation should've succeeded", e); - } - - // Glossary anchor - AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader(); - glossaryId.setGlossaryGuid(bankGlossary.getGuid()); - - // Create a category + // Category accountCategory = new AtlasGlossaryCategory(); accountCategory.setQualifiedName("acc@testBankingGlossary"); accountCategory.setDisplayName("Account categorization"); accountCategory.setShortDescription("Short description"); accountCategory.setLongDescription("Long description"); - accountCategory.setAnchor(glossaryId); - try { - accountCategory = glossaryService.createCategory(accountCategory); - } catch (AtlasBaseException e) { - fail("Account category creation should've succeeded"); - } + customerCategory = new AtlasGlossaryCategory(); + customerCategory.setQualifiedName("customer@testBankingGlossary"); + customerCategory.setDisplayName("Customer category"); + customerCategory.setShortDescription("Short description"); + customerCategory.setLongDescription("Long description"); - // Create terms + mortgageCategory = new AtlasGlossaryCategory(); + mortgageCategory.setQualifiedName("mtg@testBankingGlossary"); + mortgageCategory.setDisplayName("Mortgage categorization"); + mortgageCategory.setShortDescription("Short description"); + mortgageCategory.setLongDescription("Long description"); + + // Terms checkingAccount = new AtlasGlossaryTerm(); checkingAccount.setQualifiedName("chk_acc@testBankingGlossary"); checkingAccount.setDisplayName("A checking account"); @@ -152,7 +140,6 @@ public class GlossaryServiceTest { checkingAccount.setAbbreviation("CHK"); checkingAccount.setExamples(Arrays.asList("Personal", "Joint")); checkingAccount.setUsage("N/A"); - checkingAccount.setAnchor(glossaryId); savingsAccount = new AtlasGlossaryTerm(); savingsAccount.setQualifiedName("sav_acc@testBankingGlossary"); @@ -162,7 +149,6 @@ public class GlossaryServiceTest { savingsAccount.setAbbreviation("SAV"); savingsAccount.setExamples(Arrays.asList("Personal", "Joint")); savingsAccount.setUsage("N/A"); - savingsAccount.setAnchor(glossaryId); fixedRateMortgage = new AtlasGlossaryTerm(); fixedRateMortgage.setQualifiedName("fixed_mtg@testBankingGlossary"); @@ -172,7 +158,6 @@ public class GlossaryServiceTest { fixedRateMortgage.setAbbreviation("FMTG"); fixedRateMortgage.setExamples(Arrays.asList("15-yr", "30-yr")); fixedRateMortgage.setUsage("N/A"); - fixedRateMortgage.setAnchor(glossaryId); adjustableRateMortgage = new AtlasGlossaryTerm(); adjustableRateMortgage.setQualifiedName("arm_mtg@testBankingGlossary"); @@ -182,25 +167,53 @@ public class GlossaryServiceTest { adjustableRateMortgage.setAbbreviation("ARMTG"); adjustableRateMortgage.setExamples(Arrays.asList("5/1", "7/1", "10/1")); adjustableRateMortgage.setUsage("N/A"); + + + } + + @Test(groups = "Glossary.CREATE") + public void testCreateGlossary() { + try { + AtlasGlossary created = glossaryService.createGlossary(bankGlossary); + bankGlossary.setGuid(created.getGuid()); + created = glossaryService.createGlossary(creditUnionGlossary); + creditUnionGlossary.setGuid(created.getGuid()); + } catch (AtlasBaseException e) { + fail("Glossary creation should've succeeded", e); + } + + // Duplicate create calls should fail with 409 Conflict + try { + glossaryService.createGlossary(bankGlossary); + fail("Glossary duplicate creation should've failed"); + } catch (AtlasBaseException e) { + assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.GLOSSARY_ALREADY_EXISTS); + } + try { + glossaryService.createGlossary(creditUnionGlossary); + fail("Glossary duplicate creation should've failed"); + } catch (AtlasBaseException e) { + assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.GLOSSARY_ALREADY_EXISTS); + } + + // Glossary anchor + AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader(); + glossaryId.setGlossaryGuid(bankGlossary.getGuid()); + + // Create terms + checkingAccount.setAnchor(glossaryId); + savingsAccount.setAnchor(glossaryId); + fixedRateMortgage.setAnchor(glossaryId); + adjustableRateMortgage.setAnchor(glossaryId); // Create glossary categories - customerCategory = new AtlasGlossaryCategory(); - customerCategory.setQualifiedName("customer@testBankingGlossary"); - customerCategory.setDisplayName("Customer category"); - customerCategory.setShortDescription("Short description"); - customerCategory.setLongDescription("Long description"); + accountCategory.setAnchor(glossaryId); customerCategory.setAnchor(glossaryId); - - mortgageCategory = new AtlasGlossaryCategory(); - mortgageCategory.setQualifiedName("mtg@testBankingGlossary"); - mortgageCategory.setDisplayName("Mortgage categorization"); - mortgageCategory.setShortDescription("Short description"); - mortgageCategory.setLongDescription("Long description"); mortgageCategory.setAnchor(glossaryId); } - @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary") + @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCategoryCreation") public void testTermCreationWithoutAnyRelations() { try { checkingAccount = glossaryService.createTerm(checkingAccount); @@ -231,11 +244,11 @@ public class GlossaryServiceTest { } } - @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary") + @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCategoryCreation") public void testTermCreationWithCategory() { try { AtlasTermCategorizationHeader termCategorizationHeader = new AtlasTermCategorizationHeader(); - termCategorizationHeader.setCategoryGuid(accountCategory.getGuid()); + termCategorizationHeader.setCategoryGuid(mortgageCategory.getGuid()); termCategorizationHeader.setDescription("Test description"); termCategorizationHeader.setStatus(AtlasTermRelationshipStatus.DRAFT); @@ -253,8 +266,16 @@ public class GlossaryServiceTest { @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary") public void testCategoryCreation() { try { - List<AtlasGlossaryCategory> categories = glossaryService.createCategories(Arrays.asList(customerCategory, mortgageCategory)); - customerCategory.setGuid(categories.get(0).getGuid()); + customerCategory = glossaryService.createCategory(customerCategory); + + AtlasRelatedCategoryHeader parentHeader = new AtlasRelatedCategoryHeader(); + parentHeader.setCategoryGuid(customerCategory.getGuid()); + + // Test parent relation + accountCategory.setParentCategory(parentHeader); + List<AtlasGlossaryCategory> categories = glossaryService.createCategories(Arrays.asList(accountCategory, mortgageCategory)); + + accountCategory.setGuid(categories.get(0).getGuid()); mortgageCategory.setGuid(categories.get(1).getGuid()); } catch (AtlasBaseException e) { fail("Category creation should've succeeded", e); @@ -390,15 +411,21 @@ public class GlossaryServiceTest { savingsAccount = glossaryService.getTerm(savingsAccount.getGuid()); checkingAccount.setAnchor(newGlossaryHeader); + checkingAccount.setSeeAlso(null); savingsAccount.setAnchor(newGlossaryHeader); + savingsAccount.setSeeAlso(null); } catch (AtlasBaseException e) { fail("Term fetch for migration should've succeeded", e); } try { - glossaryService.updateTerm(checkingAccount); - glossaryService.updateTerm(savingsAccount); + checkingAccount = glossaryService.updateTerm(checkingAccount); + assertNotNull(checkingAccount); + assertTrue(CollectionUtils.isEmpty(checkingAccount.getSeeAlso())); + savingsAccount = glossaryService.updateTerm(savingsAccount); + assertNotNull(savingsAccount); + assertTrue(CollectionUtils.isEmpty(savingsAccount.getSeeAlso())); } catch (AtlasBaseException e) { fail("Term anchor change should've succeeded", e); } @@ -426,9 +453,11 @@ public class GlossaryServiceTest { } customerCategory.setAnchor(newGlossaryHeader); + customerCategory.setChildrenCategories(null); try { - glossaryService.updateCategory(customerCategory); + customerCategory = glossaryService.updateCategory(customerCategory); + assertTrue(CollectionUtils.isEmpty(customerCategory.getChildrenCategories())); } catch (AtlasBaseException e) { fail("Category anchor change should've succeeded"); } @@ -447,6 +476,7 @@ public class GlossaryServiceTest { assertNotNull(accountCategory); try { accountCategory = glossaryService.getCategory(accountCategory.getGuid()); + assertTrue(CollectionUtils.isEmpty(accountCategory.getTerms())); } catch (AtlasBaseException e) { fail("Fetch of accountCategory should've succeeded", e); } @@ -515,24 +545,17 @@ public class GlossaryServiceTest { assertNotNull(customerCategory); try { customerCategory = glossaryService.getCategory(customerCategory.getGuid()); + assertNull(customerCategory.getParentCategory()); + assertNotNull(customerCategory.getChildrenCategories()); + assertEquals(customerCategory.getChildrenCategories().size(), 1); // Only account category } catch (AtlasBaseException e) { fail("Fetch of accountCategory should've succeeded", e); } - List<AtlasGlossaryCategory> categories = new ArrayList<>(); - for (AtlasGlossaryCategory category : Arrays.asList(accountCategory, mortgageCategory)) { - try { - categories.add(glossaryService.getCategory(category.getGuid())); - } catch (AtlasBaseException e) { - fail("Category fetch should've succeeded"); - } - } - for (AtlasGlossaryCategory category : categories) { - AtlasRelatedCategoryHeader id = new AtlasRelatedCategoryHeader(); - id.setCategoryGuid(category.getGuid()); - id.setDescription("Sub-category of customer"); - customerCategory.addChild(id); - } + AtlasRelatedCategoryHeader id = new AtlasRelatedCategoryHeader(); + id.setCategoryGuid(mortgageCategory.getGuid()); + id.setDescription("Sub-category of customer"); + customerCategory.addChild(id); try { AtlasGlossaryCategory updateGlossaryCategory = glossaryService.updateCategory(customerCategory); @@ -544,7 +567,7 @@ public class GlossaryServiceTest { fail("Sub category addition should've succeeded", e); } - for (AtlasGlossaryCategory childCategory : categories) { + for (AtlasGlossaryCategory childCategory : Arrays.asList(accountCategory, mortgageCategory)) { try { AtlasGlossaryCategory child = glossaryService.getCategory(childCategory.getGuid()); assertNotNull(child); http://git-wip-us.apache.org/repos/asf/atlas/blob/cabc1e55/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java index f0c5d86..10fb403 100644 --- a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java +++ b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java @@ -214,6 +214,7 @@ public class GlossaryREST { * @throws AtlasBaseException * @HTTP 200 If glossary creation was successful * @HTTP 400 If Glossary definition has invalid or missing information + * @HTTP 409 If Glossary definition already exists (duplicate qualifiedName) */ @POST public AtlasGlossary createGlossary(AtlasGlossary atlasGlossary) throws AtlasBaseException { @@ -236,6 +237,7 @@ public class GlossaryREST { * @throws AtlasBaseException * @HTTP 200 If glossary term creation was successful * @HTTP 400 If Glossary term definition has invalid or missing information + * @HTTP 409 If Glossary term already exists (duplicate qualifiedName) */ @POST @Path("/term") @@ -289,6 +291,7 @@ public class GlossaryREST { * @throws AtlasBaseException * @HTTP 200 If glossary category creation was successful * @HTTP 400 If Glossary category definition has invalid or missing information + * @HTTP 409 If Glossary category already exists (duplicate qualifiedName) */ @POST @Path("/category")