Repository: atlas Updated Branches: refs/heads/master 15967a930 -> 0dad95296
http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 new file mode 100644 index 0000000..c2d2d2b --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryTermUtils.java @@ -0,0 +1,415 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.glossary; + +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.glossary.AtlasGlossaryTerm; +import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; +import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; +import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader; +import org.apache.atlas.model.instance.AtlasObjectId; +import org.apache.atlas.model.instance.AtlasRelatedObjectId; +import org.apache.atlas.model.instance.AtlasRelationship; +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; +import org.apache.atlas.type.AtlasRelationshipType; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.commons.collections.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class GlossaryTermUtils extends GlossaryUtils { + private static final Logger LOG = LoggerFactory.getLogger(GlossaryTermUtils.class); + private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled(); + + protected GlossaryTermUtils(AtlasRelationshipStore relationshipStore, AtlasTypeRegistry typeRegistry) { + super(relationshipStore, typeRegistry); + } + + public void processTermRelations(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { + if (DEBUG_ENABLED) { + LOG.debug("==> GlossaryTermUtils.processTermRelations({}, {}, {})", updatedTerm, existing, op); + } + + processTermAnchor(updatedTerm, existing, op); + processRelatedTerms(updatedTerm, existing, op); + processAssociatedCategories(updatedTerm, existing, op); + + if (DEBUG_ENABLED) { + LOG.debug("<== GlossaryTermUtils.processTermRelations()"); + } + } + + public void processTermAssignments(AtlasGlossaryTerm glossaryTerm, Collection<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException { + if (DEBUG_ENABLED) { + LOG.debug("==> GlossaryTermUtils.processTermAssignments({}, {})", glossaryTerm, relatedObjectIds); + } + + Objects.requireNonNull(glossaryTerm); + + Set<AtlasRelatedObjectId> assignedEntities = glossaryTerm.getAssignedEntities(); + for (AtlasRelatedObjectId objectId : relatedObjectIds) { + if (CollectionUtils.isNotEmpty(assignedEntities) && assignedEntities.contains(objectId)) { + if (DEBUG_ENABLED) { + LOG.debug("Skipping already assigned entity {}", objectId); + continue; + } + } + + if (DEBUG_ENABLED) { + LOG.debug("Assigning term guid={}, to entity guid = {}", glossaryTerm.getGuid(), objectId.getGuid()); + } + createRelationship(defineTermAssignment(glossaryTerm.getGuid(), objectId)); + } + + if (DEBUG_ENABLED) { + LOG.debug("<== GlossaryTermUtils.processTermAssignments()"); + } + } + + public void processTermDissociation(AtlasGlossaryTerm glossaryTerm, Collection<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException { + if (DEBUG_ENABLED) { + LOG.debug("==> GlossaryTermUtils.processTermDissociation({}, {}, {})", glossaryTerm.getGuid(), relatedObjectIds, glossaryTerm); + } + + Objects.requireNonNull(glossaryTerm); + if (CollectionUtils.isNotEmpty(relatedObjectIds)) { + for (AtlasRelatedObjectId relatedObjectId : relatedObjectIds) { + if (DEBUG_ENABLED) { + LOG.debug("Removing term guid={}, from entity guid = {}", glossaryTerm.getGuid(), relatedObjectId.getGuid()); + } + if (Objects.isNull(relatedObjectId.getRelationshipGuid())) { + throw new AtlasBaseException(AtlasErrorCode.TERM_DISSOCIATION_MISSING_RELATION_GUID); + } + relationshipStore.deleteById(relatedObjectId.getRelationshipGuid()); + } + } + + if (DEBUG_ENABLED) { + LOG.debug("<== GlossaryTermUtils.processTermDissociation()"); + } + } + + private void processTermAnchor(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { + AtlasGlossaryHeader existingAnchor = existing.getAnchor(); + AtlasGlossaryHeader updatedTermAnchor = updatedTerm.getAnchor(); + + switch (op) { + case CREATE: + if (Objects.isNull(updatedTermAnchor.getGlossaryGuid())) { + throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID); + } else { + if (DEBUG_ENABLED) { + LOG.debug("Creating relation between glossary = {} and term = {}", updatedTermAnchor.getGlossaryGuid(), existing.getDisplayName()); + } + createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), existing.getGuid())); + } + break; + case UPDATE: + if (!Objects.equals(updatedTermAnchor, existingAnchor)) { + if (Objects.isNull(updatedTermAnchor.getGlossaryGuid())) { + throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID); + } + + if (DEBUG_ENABLED) { + LOG.debug("Updating relation between glossary = {} and term = {}", updatedTermAnchor.getGlossaryGuid(), existing.getDisplayName()); + } + relationshipStore.deleteById(existingAnchor.getRelationGuid()); + createRelationship(defineTermAnchorRelation(updatedTermAnchor.getGlossaryGuid(), existing.getGuid())); + } + break; + case DELETE: + if (Objects.nonNull(existingAnchor)) { + if (DEBUG_ENABLED) { + LOG.debug("Deleting term anchor"); + } + relationshipStore.deleteById(existingAnchor.getRelationGuid()); + } + break; + } + } + + private void processRelatedTerms(AtlasGlossaryTerm updatedTerm, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { + Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> newRelatedTerms = updatedTerm.getRelatedTerms(); + Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> existingRelatedTerms = existing.getRelatedTerms(); + switch (op) { + case CREATE: + for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : newRelatedTerms.entrySet()) { + AtlasGlossaryTerm.Relation relation = entry.getKey(); + Set<AtlasRelatedTermHeader> terms = entry.getValue(); + if (Objects.nonNull(terms)) { + if (DEBUG_ENABLED) { + LOG.debug("{} relation {} for term = {}", op, relation, existing.getGuid()); + LOG.debug("Related Term count = {}", terms.size()); + } + createTermRelationships(existing, relation, terms); + } + } + break; + case UPDATE: + for (AtlasGlossaryTerm.Relation relation : AtlasGlossaryTerm.Relation.values()) { + Set<AtlasRelatedTermHeader> existingTermHeaders = existingRelatedTerms.get(relation); + Set<AtlasRelatedTermHeader> newTermHeaders = newRelatedTerms.get(relation); + + // No existing term relations, create all + if (CollectionUtils.isEmpty(existingTermHeaders)) { + if (DEBUG_ENABLED) { + LOG.debug("Creating new term relations, relation = {}, terms = {}", relation, + Objects.nonNull(newTermHeaders) ? newTermHeaders.size() : "none"); + } + createTermRelationships(existing, relation, newTermHeaders); + continue; + } + + // Existing term relations but nothing in updated object, remove all + if (CollectionUtils.isEmpty(newTermHeaders)) { + if (DEBUG_ENABLED) { + LOG.debug("Deleting existing term relations, relation = {}, terms = {}", relation, existingTermHeaders.size()); + } + deleteTermRelationships(relation, existingTermHeaders); + continue; + } + // Determine what to update, delete or create + Set<AtlasRelatedTermHeader> toCreate = newTermHeaders + .stream() + .filter(t -> Objects.isNull(t.getRelationGuid())) + .collect(Collectors.toSet()); + Set<AtlasRelatedTermHeader> toUpdate = newTermHeaders + .stream() + .filter(t -> Objects.nonNull(t.getRelationGuid()) && existingTermHeaders.contains(t)) + .collect(Collectors.toSet()); + Set<AtlasRelatedTermHeader> toDelete = existingTermHeaders + .stream() + .filter(t -> !toCreate.contains(t) && !toUpdate.contains(t)) + .collect(Collectors.toSet()); + + createTermRelationships(existing, relation, toCreate); + updateTermRelationships(relation, toUpdate); + deleteTermRelationships(relation, toDelete); + + } + break; + case DELETE: + for (AtlasGlossaryTerm.Relation relation : AtlasGlossaryTerm.Relation.values()) { + // No existing term relations, create all + Set<AtlasRelatedTermHeader> existingTermHeaders = existingRelatedTerms.get(relation); + deleteTermRelationships(relation, existingTermHeaders); + } + break; + } + } + + private void processAssociatedCategories(AtlasGlossaryTerm newObj, AtlasGlossaryTerm existing, RelationshipOperation op) throws AtlasBaseException { + Set<AtlasTermCategorizationHeader> newCategories = newObj.getCategories(); + Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories(); + 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); + } + break; + case UPDATE: + // If no existing categories are present then create all existing ones + if (CollectionUtils.isEmpty(existingCategories)) { + if (DEBUG_ENABLED) { + LOG.debug("Creating new term categorization, term = {}, categories = {}", existing.getGuid(), + Objects.nonNull(newCategories) ? newCategories.size() : "none"); + } + createTermCategorizationRelationships(existing, newCategories); + break; + } + + // If no new categories are present then delete all existing ones + if (CollectionUtils.isEmpty(newCategories)) { + if (DEBUG_ENABLED) { + LOG.debug("Deleting term categorization, term = {}, categories = {}", existing.getGuid(), existingCategories.size()); + } + deleteCategorizationRelationship(existingCategories); + break; + } + + Set<AtlasTermCategorizationHeader> toCreate = newCategories + .stream() + .filter(c -> Objects.isNull(c.getRelationGuid())) + .collect(Collectors.toSet()); + createTermCategorizationRelationships(existing, toCreate); + Set<AtlasTermCategorizationHeader> toUpdate = newCategories + .stream() + .filter(c -> Objects.nonNull(c.getRelationGuid()) && existingCategories.contains(c)) + .collect(Collectors.toSet()); + updateTermCategorizationRelationships(existing, toUpdate); + Set<AtlasTermCategorizationHeader> toDelete = existingCategories + .stream() + .filter(c -> !toCreate.contains(c) && !toUpdate.contains(c)) + .collect(Collectors.toSet()); + deleteCategorizationRelationship(toDelete); + break; + case DELETE: + deleteCategorizationRelationship(existingCategories); + break; + } + } + + private void createTermCategorizationRelationships(AtlasGlossaryTerm existing, Set<AtlasTermCategorizationHeader> categories) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(categories)) { + Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories(); + for (AtlasTermCategorizationHeader categorizationHeader : categories) { + if (Objects.nonNull(existingCategories) && existingCategories.contains(categorizationHeader)) { + if (DEBUG_ENABLED) { + LOG.debug("Skipping existing category guid={}", categorizationHeader.getCategoryGuid()); + } + continue; + } + if (DEBUG_ENABLED) { + LOG.debug("Creating relation between term = {} and category = {}", existing.getGuid(), categorizationHeader.getDisplayText()); + } + createRelationship(defineCategorizedTerm(categorizationHeader, existing.getGuid())); + } + } + } + + private void updateTermCategorizationRelationships(AtlasGlossaryTerm existing, Set<AtlasTermCategorizationHeader> toUpdate) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(toUpdate)) { + for (AtlasTermCategorizationHeader categorizationHeader : toUpdate) { + if (DEBUG_ENABLED) { + LOG.debug("Updating relation between term = {} and category = {}", existing.getGuid(), categorizationHeader.getDisplayText()); + } + AtlasRelationship relationship = relationshipStore.getById(categorizationHeader.getRelationGuid()); + updateRelationshipAttributes(relationship, categorizationHeader); + relationshipStore.update(relationship); + } + } + } + + private void deleteCategorizationRelationship(Set<AtlasTermCategorizationHeader> existingCategories) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(existingCategories)) { + for (AtlasTermCategorizationHeader categorizationHeader : existingCategories) { + if (DEBUG_ENABLED) { + LOG.debug("Deleting relation guid = {}, text = {}", categorizationHeader.getRelationGuid(), categorizationHeader.getDisplayText()); + } + relationshipStore.deleteById(categorizationHeader.getRelationGuid()); + } + } + } + + private void createTermRelationships(AtlasGlossaryTerm existing, AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(terms)) { + Set<AtlasRelatedTermHeader> existingRelations = existing.getRelatedTerms().get(relation); + for (AtlasRelatedTermHeader term : terms) { + if (Objects.nonNull(existingRelations) && existingRelations.contains(term)) { + if (DEBUG_ENABLED) { + LOG.debug("Skipping existing term relation termGuid={}", term.getTermGuid()); + } + continue; + } + if (DEBUG_ENABLED) { + LOG.debug("Creating new term relation = {}, terms = {}", relation, term.getDisplayText()); + } + createRelationship(defineTermRelation(relation.getRelationName(), existing.getGuid(), term)); + } + } + } + + private void updateTermRelationships(AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(terms)) { + for (AtlasRelatedTermHeader term : terms) { + if (DEBUG_ENABLED) { + LOG.debug("Updating term relation = {}, terms = {}", relation, term.getDisplayText()); + } + AtlasRelationship relationship = relationshipStore.getById(term.getRelationGuid()); + updateRelationshipAttributes(relationship, term); + relationshipStore.update(relationship); + } + } + } + + private void deleteTermRelationships(AtlasGlossaryTerm.Relation relation, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException { + if (CollectionUtils.isNotEmpty(terms)) { + for (AtlasRelatedTermHeader termHeader : terms) { + if (DEBUG_ENABLED) { + LOG.debug("Deleting term relation = {}, terms = {}", relation, termHeader.getDisplayText()); + } + relationshipStore.deleteById(termHeader.getRelationGuid()); + } + } + } + + private AtlasRelationship defineTermAnchorRelation(String glossaryGuid, String termGuid) { + AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(TERM_ANCHOR); + AtlasStruct defaultAttrs = relationshipType.createDefaultValue(); + + return new AtlasRelationship(TERM_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(termGuid), defaultAttrs.getAttributes()); + } + + private AtlasRelationship defineTermRelation(String relation, String end1TermGuid, AtlasRelatedTermHeader end2RelatedTerm) { + AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(relation); + AtlasStruct defaultAttrs = relationshipType.createDefaultValue(); + + AtlasRelationship relationship = new AtlasRelationship(relation, new AtlasObjectId(end1TermGuid), new AtlasObjectId(end2RelatedTerm.getTermGuid()), defaultAttrs.getAttributes()); + updateRelationshipAttributes(relationship, end2RelatedTerm); + return relationship; + } + + private AtlasRelationship defineCategorizedTerm(AtlasTermCategorizationHeader relatedCategoryId, String termId) { + AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(TERM_CATEGORIZATION); + AtlasStruct defaultAttrs = relationshipType.createDefaultValue(); + + AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(relatedCategoryId.getCategoryGuid()), new AtlasObjectId(termId), defaultAttrs.getAttributes()); + updateRelationshipAttributes(relationship, relatedCategoryId); + return relationship; + } + + private AtlasRelationship defineTermAssignment(String termGuid, AtlasRelatedObjectId relatedObjectId) { + AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(TERM_ASSIGNMENT); + AtlasStruct defaultAttrs = relationshipType.createDefaultValue(); + + AtlasObjectId end1 = new AtlasObjectId(termGuid); + AtlasRelationship relationship = new AtlasRelationship(TERM_ASSIGNMENT, end1, relatedObjectId, defaultAttrs.getAttributes()); + updateRelationshipAttributes(relationship, relatedObjectId); + return relationship; + } + + private void updateRelationshipAttributes(AtlasRelationship relationship, AtlasTermCategorizationHeader categorizationHeader) { + if (Objects.nonNull(relationship)) { + relationship.setAttribute(TERM_RELATION_ATTR_DESCRIPTION, categorizationHeader.getDescription()); + if (Objects.nonNull(categorizationHeader.getStatus())) { + relationship.setAttribute(TERM_RELATION_ATTR_STATUS, categorizationHeader.getStatus().name()); + } + } + } + + private void updateRelationshipAttributes(AtlasRelationship relationship, AtlasRelatedObjectId relatedObjectId) { + AtlasStruct relationshipAttributes = relatedObjectId.getRelationshipAttributes(); + if (Objects.nonNull(relationshipAttributes)) { + for (Map.Entry<String, Object> attrEntry : relationshipAttributes.getAttributes().entrySet()) { + relationship.setAttribute(attrEntry.getKey(), attrEntry.getValue()); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 new file mode 100644 index 0000000..38555cc --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryUtils.java @@ -0,0 +1,86 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.glossary; + +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; +import org.apache.atlas.model.instance.AtlasRelationship; +import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; +import org.apache.atlas.type.AtlasTypeRegistry; + +import java.util.Objects; + +public abstract class GlossaryUtils { + + public static final String TERM_ASSIGNMENT_ATTR_DESCRIPTION = "description"; + public static final String TERM_ASSIGNMENT_ATTR_EXPRESSION = "expression"; + public static final String TERM_ASSIGNMENT_ATTR_STATUS = "status"; + public static final String TERM_ASSIGNMENT_ATTR_CONFIDENCE = "confidence"; + public static final String TERM_ASSIGNMENT_ATTR_CREATED_BY = "createdBy"; + 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"; + // Relation name constants + 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"; + protected static final String TERM_CATEGORIZATION = ATLAS_GLOSSARY_PREFIX + "TermCategorization"; + protected static final String TERM_ASSIGNMENT = ATLAS_GLOSSARY_PREFIX + "SemanticAssignment"; + protected static final String TERM_RELATION_ATTR_EXPRESSION = "expression"; + protected static final String TERM_RELATION_ATTR_DESCRIPTION = "description"; + protected static final String TERM_RELATION_ATTR_STEWARD = "steward"; + 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; + + protected GlossaryUtils(final AtlasRelationshipStore relationshipStore, final AtlasTypeRegistry typeRegistry) { + this.relationshipStore = relationshipStore; + this.typeRegistry = typeRegistry; + } + + protected void createRelationship(AtlasRelationship relationship) throws AtlasBaseException { + try { + relationshipStore.create(relationship); + } catch (AtlasBaseException e) { + if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIP_ALREADY_EXISTS)) { + throw e; + } + } + } + + protected void updateRelationshipAttributes(AtlasRelationship relationship, AtlasRelatedTermHeader relatedTermHeader) { + if (Objects.nonNull(relationship)) { + relationship.setAttribute(TERM_RELATION_ATTR_EXPRESSION, relatedTermHeader.getExpression()); + relationship.setAttribute(TERM_RELATION_ATTR_DESCRIPTION, relatedTermHeader.getDescription()); + relationship.setAttribute(TERM_RELATION_ATTR_STEWARD, relatedTermHeader.getSteward()); + relationship.setAttribute(TERM_RELATION_ATTR_SOURCE, relatedTermHeader.getSource()); + if (Objects.nonNull(relatedTermHeader.getStatus())) { + relationship.setAttribute(TERM_RELATION_ATTR_STATUS, relatedTermHeader.getStatus().name()); + } + } + } + + enum RelationshipOperation { + CREATE, UPDATE, DELETE + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java index 1473749..6a3cc36 100644 --- a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java +++ b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java @@ -113,7 +113,13 @@ public class DataAccess { List<AtlasBaseModelObject> ret = new ArrayList<>(); for (T object : objects) { - ret.add(load(object)); + try { + ret.add(load(object)); + } catch (AtlasBaseException e) { + // In case of bulk load, some entities might be in deleted state causing an exception to be thrown + // by the single load API call + LOG.warn("Bulk load encountered an error.", e); + } } return (Iterable<T>) ret; http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AtlasGlossaryTermDTO.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AtlasGlossaryTermDTO.java b/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AtlasGlossaryTermDTO.java index 3f8bfe2..92bb242 100644 --- a/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AtlasGlossaryTermDTO.java +++ b/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AtlasGlossaryTermDTO.java @@ -20,7 +20,6 @@ package org.apache.atlas.repository.ogm.glossary; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.glossary.AtlasGlossaryTerm; import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasRelatedObjectId; import org.apache.atlas.model.instance.AtlasRelationship; import org.apache.atlas.type.AtlasTypeRegistry; @@ -92,12 +91,7 @@ public class AtlasGlossaryTermDTO extends AbstractGlossaryDTO<AtlasGlossaryTerm> if (assignedEntity instanceof AtlasRelatedObjectId) { AtlasRelatedObjectId id = (AtlasRelatedObjectId) assignedEntity; if (id.getRelationshipStatus() == AtlasRelationship.Status.ACTIVE) { - AtlasEntityHeader entityHeader = new AtlasEntityHeader(id.getTypeName(), id.getGuid(), id.getUniqueAttributes()); - if (entityHeader.getAttributes() == null) { - entityHeader.setAttributes(new HashMap<>()); - } - entityHeader.getAttributes().put("relationGuid", id.getRelationshipGuid()); - ret.addAssignedEntity(entityHeader); + ret.addAssignedEntity(id); } } } http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java index 7b2806e..cc59c36 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java @@ -1,3 +1,4 @@ + /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 9add9b5..f8d967e 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 @@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.TimeBoundary; +import org.apache.atlas.model.glossary.enums.AtlasTermAssignmentStatus; import org.apache.atlas.model.glossary.relations.AtlasTermAssignmentHeader; import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification.PropagationState; @@ -71,30 +72,16 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import static org.apache.atlas.glossary.GlossaryUtils.*; import static org.apache.atlas.model.instance.AtlasClassification.PropagationState.ACTIVE; import static org.apache.atlas.model.instance.AtlasClassification.PropagationState.DELETED; import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*; import static org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags.ONE_TO_TWO; -import static org.apache.atlas.repository.Constants.*; -import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX; -import static org.apache.atlas.repository.graph.GraphHelper.addToPropagatedTraitNames; -import static org.apache.atlas.repository.graph.GraphHelper.getAdjacentEdgesByLabel; -import static org.apache.atlas.repository.graph.GraphHelper.getAllClassificationEdges; -import static org.apache.atlas.repository.graph.GraphHelper.getAllTraitNames; -import static org.apache.atlas.repository.graph.GraphHelper.getAssociatedEntityVertex; -import static org.apache.atlas.repository.graph.GraphHelper.getBlockedClassificationIds; -import static org.apache.atlas.repository.graph.GraphHelper.getClassificationEdge; -import static org.apache.atlas.repository.graph.GraphHelper.getClassificationEdgeState; -import static org.apache.atlas.repository.graph.GraphHelper.getGuid; -import static org.apache.atlas.repository.graph.GraphHelper.getIncomingEdgesByLabel; -import static org.apache.atlas.repository.graph.GraphHelper.getOutGoingEdgesByLabel; -import static org.apache.atlas.repository.graph.GraphHelper.getPropagateTags; -import static org.apache.atlas.repository.graph.GraphHelper.getPropagatedClassificationEdge; -import static org.apache.atlas.repository.graph.GraphHelper.getRelationshipGuid; -import static org.apache.atlas.repository.graph.GraphHelper.getTypeName; -import static org.apache.atlas.repository.graph.GraphHelper.isPropagatedClassificationEdge; -import static org.apache.atlas.repository.graph.GraphHelper.isPropagationEnabled; -import static org.apache.atlas.repository.graph.GraphHelper.removeFromPropagatedTraitNames; +import static org.apache.atlas.repository.Constants.CLASSIFICATION_ENTITY_GUID; +import static org.apache.atlas.repository.Constants.CLASSIFICATION_LABEL; +import static org.apache.atlas.repository.Constants.CLASSIFICATION_VALIDITY_PERIODS_KEY; +import static org.apache.atlas.repository.Constants.TERM_ASSIGNMENT_LABEL; +import static org.apache.atlas.repository.graph.GraphHelper.*; import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex; import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection; import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH; @@ -105,7 +92,11 @@ import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelation public final class EntityGraphRetriever { private static final Logger LOG = LoggerFactory.getLogger(EntityGraphRetriever.class); + private static final String TERM_RELATION_NAME = "__AtlasGlossarySemanticAssignment"; + private static final String GLOSSARY_TERM_DISPLAY_NAME_ATTR = "__AtlasGlossaryTerm.displayName"; + private final String NAME = "name"; + private final String DISPLAY_NAME = "displayName"; private final String DESCRIPTION = "description"; private final String OWNER = "owner"; private final String CREATE_TIME = "createTime"; @@ -368,7 +359,9 @@ public final class EntityGraphRetriever { ret.setStatus(GraphHelper.getStatus(entityVertex)); ret.setClassificationNames(getAllTraitNames(entityVertex)); - // TODO: Add the term mapping here + List<AtlasTermAssignmentHeader> termAssignmentHeaders = mapAssignedTerms(entityVertex); + ret.setMeanings(termAssignmentHeaders); + ret.setMeaningNames(termAssignmentHeaders.stream().map(AtlasTermAssignmentHeader::getDisplayText).collect(Collectors.toList())); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName); @@ -410,6 +403,7 @@ public final class EntityGraphRetriever { } } } + } return ret; @@ -503,6 +497,85 @@ public final class EntityGraphRetriever { return ret; } + public List<AtlasTermAssignmentHeader> mapAssignedTerms(AtlasVertex entityVertex) throws AtlasBaseException { + List<AtlasTermAssignmentHeader> ret = new ArrayList<>(); + + 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) { + ret.add(toTermAssignmentHeader(edge)); + } + } + } + + return ret; + } + + private AtlasTermAssignmentHeader toTermAssignmentHeader(final AtlasEdge edge) { + AtlasTermAssignmentHeader ret = new AtlasTermAssignmentHeader(); + + AtlasVertex termVertex = edge.getOutVertex(); + + String guid = GraphHelper.getGuid(termVertex); + if (guid != null) { + ret.setTermGuid(guid); + } + + String relationGuid = edge.getProperty(Constants.RELATIONSHIP_GUID_PROPERTY_KEY, String.class); + if (relationGuid != null) { + ret.setRelationGuid(relationGuid); + } + + Object displayName = GraphHelper.getProperty(termVertex, GLOSSARY_TERM_DISPLAY_NAME_ATTR); + if (displayName instanceof String) { + ret.setDisplayText((String) displayName); + } + + String description = edge.getProperty(TERM_ASSIGNMENT_ATTR_DESCRIPTION, String.class); + if (description != null) { + ret.setDescription(description); + } + + String expression = edge.getProperty(TERM_ASSIGNMENT_ATTR_EXPRESSION, String.class); + if (expression != null) { + ret.setExpression(expression); + } + + String status = edge.getProperty(TERM_ASSIGNMENT_ATTR_STATUS, String.class); + if (status != null) { + AtlasTermAssignmentStatus assignmentStatus = AtlasTermAssignmentStatus.valueOf(status); + ret.setStatus(assignmentStatus); + } + + Integer confidence = edge.getProperty(TERM_ASSIGNMENT_ATTR_CONFIDENCE, Integer.class); + if (confidence != null) { + ret.setConfidence(confidence); + } + + String createdBy = edge.getProperty(TERM_ASSIGNMENT_ATTR_CREATED_BY, String.class); + if (createdBy != null) { + ret.setCreatedBy(createdBy); + } + + String steward = edge.getProperty(TERM_ASSIGNMENT_ATTR_STEWARD, String.class); + if (steward != null) { + ret.setSteward(steward); + } + + String source = edge.getProperty(TERM_ASSIGNMENT_ATTR_SOURCE, String.class); + if (source != null) { + ret.setSource(source); + } + + return ret; + } + private void mapClassifications(AtlasVertex entityVertex, AtlasEntity entity) throws AtlasBaseException { List<AtlasEdge> edges = getAllClassificationEdges(entityVertex); @@ -881,6 +954,10 @@ public final class EntityGraphRetriever { ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME)); if (ret == null) { + ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME)); + } + + if (ret == null) { ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME)); } } http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 62a0cb4..0294550 100644 --- a/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/glossary/GlossaryServiceTest.java @@ -28,8 +28,10 @@ import org.apache.atlas.model.glossary.enums.AtlasTermRelationshipStatus; import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; 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.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.AtlasRelatedObjectId; import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.repository.impexp.ZipFileResourceTestUtils; import org.apache.atlas.repository.store.graph.AtlasEntityStore; @@ -49,11 +51,14 @@ import javax.inject.Inject; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Map; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; @Guice(modules = TestModules.TestOnlyModule.class) public class GlossaryServiceTest { @@ -68,11 +73,21 @@ public class GlossaryServiceTest { @Inject private AtlasEntityStore entityStore; - private AtlasGlossary bankGlossary; + private AtlasGlossary bankGlossary, creditUnionGlossary; private AtlasGlossaryTerm checkingAccount, savingsAccount, fixedRateMortgage, adjustableRateMortgage; private AtlasGlossaryCategory customerCategory, accountCategory, mortgageCategory; - private AtlasEntityHeader testEntityHeader; + private AtlasRelatedObjectId relatedObjectId; + + @DataProvider + public static Object[][] getGlossaryTermsProvider() { + return new Object[][]{ + // offset, limit, expected + {0, -1, 4}, + {0, 2, 2}, + {2, 5, 2}, + }; + } @BeforeClass public void setupSampleGlossary() { @@ -93,19 +108,42 @@ public class GlossaryServiceTest { bankGlossary.setUsage("N/A"); bankGlossary.setLanguage("en-US"); + creditUnionGlossary = new AtlasGlossary(); + creditUnionGlossary.setQualifiedName("testCreditUnionGlossary"); + creditUnionGlossary.setDisplayName("Credit union glossary"); + creditUnionGlossary.setShortDescription("Short description"); + creditUnionGlossary.setLongDescription("Long description"); + 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); } - } - @Test(groups = "Glossary.CREATE", dependsOnMethods = {"testCreateGlossary"}) - public void testCreateGlossaryTerms() { + // Glossary anchor AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader(); glossaryId.setGlossaryGuid(bankGlossary.getGuid()); + // Create a 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"); + } + + // Create terms checkingAccount = new AtlasGlossaryTerm(); checkingAccount.setQualifiedName("chk_acc@testBankingGlossary"); checkingAccount.setDisplayName("A checking account"); @@ -146,22 +184,7 @@ public class GlossaryServiceTest { adjustableRateMortgage.setUsage("N/A"); adjustableRateMortgage.setAnchor(glossaryId); - try { - List<AtlasGlossaryTerm> terms = glossaryService.createTerms(Arrays.asList(checkingAccount, savingsAccount, fixedRateMortgage, adjustableRateMortgage)); - checkingAccount.setGuid(terms.get(0).getGuid()); - savingsAccount.setGuid(terms.get(1).getGuid()); - fixedRateMortgage.setGuid(terms.get(2).getGuid()); - adjustableRateMortgage.setGuid(terms.get(3).getGuid()); - } catch (AtlasBaseException e) { - fail("Term creation should've succeeded", e); - } - } - - @Test(groups = "Glossary.CREATE", dependsOnMethods = {"testCreateGlossaryTerms"}) - public void testCreateGlossaryCategory() { - AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader(); - glossaryId.setGlossaryGuid(bankGlossary.getGuid()); - + // Create glossary categories customerCategory = new AtlasGlossaryCategory(); customerCategory.setQualifiedName("customer@testBankingGlossary"); customerCategory.setDisplayName("Customer category"); @@ -169,47 +192,93 @@ public class GlossaryServiceTest { customerCategory.setLongDescription("Long description"); customerCategory.setAnchor(glossaryId); - accountCategory = new AtlasGlossaryCategory(); - accountCategory.setQualifiedName("acc@testBankingGlossary"); - accountCategory.setDisplayName("Account categorization"); - accountCategory.setShortDescription("Short description"); - accountCategory.setLongDescription("Long description"); - accountCategory.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") + public void testTermCreationWithoutAnyRelations() { + try { + checkingAccount = glossaryService.createTerm(checkingAccount); + assertNotNull(checkingAccount); + assertNotNull(checkingAccount.getGuid()); + } catch (AtlasBaseException e) { + fail("Term creation should've succeeded", e); + } + } + @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testTermCreationWithoutAnyRelations") + public void testTermCreateWithRelation() { try { - List<AtlasGlossaryCategory> categories = glossaryService.createCategories(Arrays.asList(customerCategory, accountCategory, mortgageCategory)); + AtlasRelatedTermHeader relatedTermHeader = new AtlasRelatedTermHeader(); + relatedTermHeader.setTermGuid(checkingAccount.getGuid()); + relatedTermHeader.setDescription("test description"); + relatedTermHeader.setExpression("test expression"); + relatedTermHeader.setSource("UT"); + relatedTermHeader.setSteward("UT"); + relatedTermHeader.setStatus(AtlasTermRelationshipStatus.ACTIVE); + savingsAccount.setSeeAlso(Collections.singleton(relatedTermHeader)); + + savingsAccount = glossaryService.createTerm(savingsAccount); + assertNotNull(savingsAccount); + assertNotNull(savingsAccount.getGuid()); + } catch (AtlasBaseException e) { + fail("Term creation with relation should've succeeded", e); + } + } + + @Test(groups = "Glossary.CREATE" , dependsOnMethods = "testCreateGlossary") + public void testTermCreationWithCategory() { + try { + AtlasTermCategorizationHeader termCategorizationHeader = new AtlasTermCategorizationHeader(); + termCategorizationHeader.setCategoryGuid(accountCategory.getGuid()); + termCategorizationHeader.setDescription("Test description"); + termCategorizationHeader.setStatus(AtlasTermRelationshipStatus.DRAFT); + + fixedRateMortgage.setCategories(Collections.singleton(termCategorizationHeader)); + adjustableRateMortgage.setCategories(Collections.singleton(termCategorizationHeader)); + + List<AtlasGlossaryTerm> terms = glossaryService.createTerms(Arrays.asList(fixedRateMortgage, adjustableRateMortgage)); + fixedRateMortgage.setGuid(terms.get(0).getGuid()); + adjustableRateMortgage.setGuid(terms.get(1).getGuid()); + } catch (AtlasBaseException e) { + fail("Term creation should've succeeded", e); + } + } + + @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()); - accountCategory.setGuid(categories.get(1).getGuid()); - mortgageCategory.setGuid(categories.get(2).getGuid()); + mortgageCategory.setGuid(categories.get(1).getGuid()); } catch (AtlasBaseException e) { fail("Category creation should've succeeded", e); } } + @DataProvider public Object[][] getAllGlossaryDataProvider() { return new Object[][]{ // limit, offset, sortOrder, expected {1, 0, SortOrder.ASCENDING, 1}, - {5, 0, SortOrder.ASCENDING, 1}, - {10, 0, SortOrder.ASCENDING, 1}, - {1, 1, SortOrder.ASCENDING, 0}, - {5, 1, SortOrder.ASCENDING, 0}, - {10, 1, SortOrder.ASCENDING, 0}, + {5, 0, SortOrder.ASCENDING, 2}, + {10, 0, SortOrder.ASCENDING, 2}, + {1, 1, SortOrder.ASCENDING, 1}, + {5, 1, SortOrder.ASCENDING, 1}, + {10, 1, SortOrder.ASCENDING, 1}, {1, 2, SortOrder.ASCENDING, 0}, {5, 2, SortOrder.ASCENDING, 0}, {10, 2, SortOrder.ASCENDING, 0}, }; } - @Test(dataProvider = "getAllGlossaryDataProvider") + @Test(dataProvider = "getAllGlossaryDataProvider", groups = "Glossary.GET", dependsOnGroups = "Glossary.CREATE") public void testGetAllGlossaries(int limit, int offset, SortOrder sortOrder, int expected) { try { List<AtlasGlossary> glossaries = glossaryService.getGlossaries(limit, offset, sortOrder); @@ -219,17 +288,6 @@ public class GlossaryServiceTest { } } - @Test(groups = "Glossary.GET", dependsOnGroups = "Glossary.CREATE") - public void testGetGlossary() { - try { - AtlasGlossary glossary = glossaryService.getGlossary(bankGlossary.getGuid()); - assertNotNull(glossary); - assertEquals(glossary.getGuid(), bankGlossary.getGuid()); - } catch (AtlasBaseException e) { - fail("Glossary fetch should've succeeded", e); - } - } - @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") public void testUpdateGlossary() { try { @@ -241,13 +299,12 @@ public class GlossaryServiceTest { assertNotNull(updatedGlossary); assertEquals(updatedGlossary.getGuid(), bankGlossary.getGuid()); assertEquals(updatedGlossary, bankGlossary); - bankGlossary = updatedGlossary; } catch (AtlasBaseException e) { fail("Glossary fetch/update should've succeeded", e); } } - @Test(dependsOnGroups = {"Glossary.GET", "Glossary.UPDATE", "Glossary.GET.postUpdate"}) // Should be the last test + @Test(dependsOnGroups = {"Glossary.MIGRATE"}) // Should be the last test public void testDeleteGlossary() { try { glossaryService.deleteGlossary(bankGlossary.getGuid()); @@ -261,19 +318,6 @@ public class GlossaryServiceTest { } } - @Test(groups = "Glossary.GET", dependsOnGroups = "Glossary.CREATE") - public void testGetGlossaryTerm() { - for (AtlasGlossaryTerm t : Arrays.asList(checkingAccount, savingsAccount, fixedRateMortgage, adjustableRateMortgage)) { - try { - AtlasGlossaryTerm glossaryTerm = glossaryService.getTerm(t.getGuid()); - assertNotNull(glossaryTerm); - assertEquals(glossaryTerm.getGuid(), t.getGuid()); - } catch (AtlasBaseException e) { - fail("Glossary term fetching should've succeeded", e); - } - } - } - @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") public void testUpdateGlossaryTerm() { List<AtlasGlossaryTerm> glossaryTerms = new ArrayList<>(); @@ -298,19 +342,6 @@ public class GlossaryServiceTest { } } - @Test(groups = "Glossary.GET", dependsOnGroups = "Glossary.CREATE") - public void testGetGlossaryCategory() { - for (AtlasGlossaryCategory c : Arrays.asList(customerCategory, accountCategory, mortgageCategory)) { - try { - AtlasGlossaryCategory glossaryCategory = glossaryService.getCategory(c.getGuid()); - assertNotNull(glossaryCategory); - assertEquals(glossaryCategory.getGuid(), c.getGuid()); - } catch (AtlasBaseException e) { - fail("Glossary category fetching should've succeeded", e); - } - } - } - @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") public void testUpdateGlossaryCategory() { List<AtlasGlossaryCategory> glossaryCategories = new ArrayList<>(); @@ -324,17 +355,91 @@ public class GlossaryServiceTest { for (AtlasGlossaryCategory c : glossaryCategories) { try { - AtlasGlossaryCategory glossaryCategory = glossaryService.getCategory(c.getGuid()); - glossaryCategory.setShortDescription("Updated short description"); - glossaryCategory.setLongDescription("Updated long description"); + c.setShortDescription("Updated short description"); + c.setLongDescription("Updated long description"); - AtlasGlossaryCategory updatedCategory = glossaryService.updateCategory(glossaryCategory); + AtlasGlossaryCategory updatedCategory = glossaryService.updateCategory(c); assertNotNull(updatedCategory); assertEquals(updatedCategory.getGuid(), c.getGuid()); } catch (AtlasBaseException e) { fail("Glossary category fetching should've succeeded", e); } } + + // Unlink children + try { + AtlasGlossaryCategory category = glossaryService.getCategory(customerCategory.getGuid()); + category.setChildrenCategories(null); + category = glossaryService.updateCategory(category); + assertNotNull(category); + assertNull(category.getChildrenCategories()); + } catch (AtlasBaseException e) { + fail("Customer category fetch should've succeeded"); + } + } + + @Test(groups = "Glossary.MIGRATE", dependsOnGroups = "Glossary.GET.postUpdate") + public void testTermMigration() { + assertNotNull(creditUnionGlossary); + + AtlasGlossaryHeader newGlossaryHeader = new AtlasGlossaryHeader(); + newGlossaryHeader.setGlossaryGuid(creditUnionGlossary.getGuid()); + + try { + checkingAccount = glossaryService.getTerm(checkingAccount.getGuid()); + savingsAccount = glossaryService.getTerm(savingsAccount.getGuid()); + + checkingAccount.setAnchor(newGlossaryHeader); + savingsAccount.setAnchor(newGlossaryHeader); + + } catch (AtlasBaseException e) { + fail("Term fetch for migration should've succeeded", e); + } + + try { + glossaryService.updateTerm(checkingAccount); + glossaryService.updateTerm(savingsAccount); + } catch (AtlasBaseException e) { + fail("Term anchor change should've succeeded", e); + } + + try { + List<AtlasGlossaryTerm> terms = glossaryService.getGlossaryTerms(creditUnionGlossary.getGuid(), 0, 5, SortOrder.ASCENDING); + assertNotNull(terms); + assertEquals(terms.size(), 2); + } catch (AtlasBaseException e) { + fail("Term fetch for glossary should've succeeded", e); + } + } + + @Test(groups = "Glossary.MIGRATE", dependsOnGroups = "Glossary.GET.postUpdate") + public void testCategoryMigration() { + assertNotNull(creditUnionGlossary); + + AtlasGlossaryHeader newGlossaryHeader = new AtlasGlossaryHeader(); + newGlossaryHeader.setGlossaryGuid(creditUnionGlossary.getGuid()); + + try { + customerCategory = glossaryService.getCategory(customerCategory.getGuid()); + } catch (AtlasBaseException e) { + fail("Category fetch for migration should've succeeded"); + } + + customerCategory.setAnchor(newGlossaryHeader); + + try { + glossaryService.updateCategory(customerCategory); + } catch (AtlasBaseException e) { + fail("Category anchor change should've succeeded"); + } + + try { + List<AtlasRelatedCategoryHeader> categories = glossaryService.getGlossaryCategories(creditUnionGlossary.getGuid(), 0, 5, SortOrder.ASCENDING); + assertNotNull(categories); + assertEquals(categories.size(), 1); + } catch (AtlasBaseException e) { + fail("Category migration should've succeeded", e); + } } @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") @@ -345,24 +450,22 @@ public class GlossaryServiceTest { } catch (AtlasBaseException e) { fail("Fetch of accountCategory should've succeeded", e); } - List<AtlasGlossaryTerm> terms = new ArrayList<>(); for (AtlasGlossaryTerm term : Arrays.asList(checkingAccount, savingsAccount)) { try { - terms.add(glossaryService.getTerm(term.getGuid())); + AtlasGlossaryTerm termEntry = glossaryService.getTerm(term.getGuid()); + AtlasRelatedTermHeader relatedTermId = new AtlasRelatedTermHeader(); + relatedTermId.setTermGuid(termEntry.getGuid()); + relatedTermId.setStatus(AtlasTermRelationshipStatus.ACTIVE); + relatedTermId.setSteward("UT"); + relatedTermId.setSource("UT"); + relatedTermId.setExpression("N/A"); + relatedTermId.setDescription("Categorization under account category"); + accountCategory.addTerm(relatedTermId); } catch (AtlasBaseException e) { fail("Term fetching should've succeeded", e); } } - for (AtlasGlossaryTerm termEntry : terms) { - AtlasRelatedTermHeader relatedTermId = new AtlasRelatedTermHeader(); - relatedTermId.setTermGuid(termEntry.getGuid()); - relatedTermId.setStatus(AtlasTermRelationshipStatus.ACTIVE); - relatedTermId.setSteward("UT"); - relatedTermId.setSource("UT"); - relatedTermId.setExpression("N/A"); - relatedTermId.setDescription("Categorization under account category"); - accountCategory.addTerm(relatedTermId); - } + try { AtlasGlossaryCategory updated = glossaryService.updateCategory(accountCategory); assertNotNull(updated.getTerms()); @@ -379,26 +482,23 @@ public class GlossaryServiceTest { fail("Fetch of accountCategory should've succeeded", e); } - terms.clear(); for (AtlasGlossaryTerm term : Arrays.asList(fixedRateMortgage, adjustableRateMortgage)) { try { - terms.add(glossaryService.getTerm(term.getGuid())); + AtlasGlossaryTerm termEntry = glossaryService.getTerm(term.getGuid()); + AtlasRelatedTermHeader relatedTermId = new AtlasRelatedTermHeader(); + relatedTermId.setTermGuid(termEntry.getGuid()); + relatedTermId.setStatus(AtlasTermRelationshipStatus.ACTIVE); + relatedTermId.setSteward("UT"); + relatedTermId.setSource("UT"); + relatedTermId.setExpression("N/A"); + relatedTermId.setDescription("Categorization under mortgage category"); + + mortgageCategory.addTerm(relatedTermId); } catch (AtlasBaseException e) { fail("Term fetching should've succeeded", e); } } - for (AtlasGlossaryTerm termEntry : terms) { - AtlasRelatedTermHeader relatedTermId = new AtlasRelatedTermHeader(); - relatedTermId.setTermGuid(termEntry.getGuid()); - relatedTermId.setStatus(AtlasTermRelationshipStatus.ACTIVE); - relatedTermId.setSteward("UT"); - relatedTermId.setSource("UT"); - relatedTermId.setExpression("N/A"); - relatedTermId.setDescription("Categorization under mortgage category"); - - mortgageCategory.addTerm(relatedTermId); - } try { AtlasGlossaryCategory updated = glossaryService.updateCategory(mortgageCategory); assertNotNull(updated.getTerms()); @@ -439,77 +539,59 @@ public class GlossaryServiceTest { assertNull(updateGlossaryCategory.getParentCategory()); assertNotNull(updateGlossaryCategory.getChildrenCategories()); assertEquals(updateGlossaryCategory.getChildrenCategories().size(), 2); - customerCategory = updateGlossaryCategory; - LOG.debug(AtlasJson.toJson(updateGlossaryCategory)); } catch (AtlasBaseException e) { fail("Sub category addition should've succeeded", e); } - } - - @Test(groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") - public void testCategoryRelation() { - AtlasGlossaryCategory parent = customerCategory; - Map<String, List<AtlasRelatedCategoryHeader>> relatedCategories; - try { - relatedCategories = glossaryService.getRelatedCategories(parent.getGuid(), 0, -1, SortOrder.ASCENDING); - assertNotNull(relatedCategories); - assertNotNull(relatedCategories.get("children")); - assertEquals(relatedCategories.get("children").size(), 2); - } catch (AtlasBaseException e) { - fail("Category fetch should've succeeded", e); - } - - for (AtlasGlossaryCategory childCategory : Arrays.asList(accountCategory, mortgageCategory)) { + for (AtlasGlossaryCategory childCategory : categories) { try { - relatedCategories = glossaryService.getRelatedCategories(childCategory.getGuid(), 0, -1, SortOrder.ASCENDING); - assertNotNull(relatedCategories.get("parent")); - assertEquals(relatedCategories.get("parent").size(), 1); + AtlasGlossaryCategory child = glossaryService.getCategory(childCategory.getGuid()); + assertNotNull(child); + assertNotNull(child.getParentCategory()); } catch (AtlasBaseException e) { - fail("Category fetch should've succeeded", e); + fail("Category fetch should've been a success", e); } } } @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE") - public void testTermAssignment() { + public void testTermAssignmentAndDissociation() { AtlasEntity assetEntity = new AtlasEntity("Asset"); assetEntity.setAttribute("qualifiedName", "testAsset"); assetEntity.setAttribute("name", "testAsset"); try { EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(assetEntity), false); - testEntityHeader = response.getFirstEntityCreated(); - assertNotNull(testEntityHeader); + AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated(); + relatedObjectId = new AtlasRelatedObjectId(); + relatedObjectId.setGuid(firstEntityCreated.getGuid()); + relatedObjectId.setTypeName(firstEntityCreated.getTypeName()); + assertNotNull(relatedObjectId); } catch (AtlasBaseException e) { fail("Entity creation should've succeeded", e); } try { - glossaryService.assignTermToEntities(fixedRateMortgage.getGuid(), Arrays.asList(testEntityHeader)); + glossaryService.assignTermToEntities(fixedRateMortgage.getGuid(), Arrays.asList(relatedObjectId)); } catch (AtlasBaseException e) { fail("Term assignment to asset should've succeeded", e); } try { - List<AtlasEntityHeader> assignedEntities = glossaryService.getAssignedEntities(fixedRateMortgage.getGuid(), 0, 1, SortOrder.ASCENDING); + List<AtlasRelatedObjectId> assignedEntities = glossaryService.getAssignedEntities(fixedRateMortgage.getGuid(), 0, 1, SortOrder.ASCENDING); assertNotNull(assignedEntities); assertEquals(assignedEntities.size(), 1); - Object relationGuid = assignedEntities.get(0).getAttribute("relationGuid"); - assertNotNull(relationGuid); - testEntityHeader.setAttribute("relationGuid", relationGuid); + String relationshipGuid = assignedEntities.get(0).getRelationshipGuid(); + assertNotNull(relationshipGuid); + relatedObjectId.setRelationshipGuid(relationshipGuid); } catch (AtlasBaseException e) { fail("Term fetch should've succeeded",e); } - } - - // FIXME: The term dissociation is not working as intended. - @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE", dependsOnMethods = "testTermAssignment") - public void testTermDissociation() { + // Dissociate term from entities try { - glossaryService.removeTermFromEntities(fixedRateMortgage.getGuid(), Arrays.asList(testEntityHeader)); + glossaryService.removeTermFromEntities(fixedRateMortgage.getGuid(), Arrays.asList(relatedObjectId)); AtlasGlossaryTerm term = glossaryService.getTerm(fixedRateMortgage.getGuid()); assertNotNull(term); assertNull(term.getAssignedEntities()); @@ -538,9 +620,9 @@ public class GlossaryServiceTest { checkingAccount.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm))); try { - AtlasGlossaryTerm updatedTerm = glossaryService.updateTerm(checkingAccount); - assertNotNull(updatedTerm.getSeeAlso()); - assertEquals(updatedTerm.getSeeAlso().size(), 1); + checkingAccount = glossaryService.updateTerm(checkingAccount); + assertNotNull(checkingAccount.getSeeAlso()); + assertEquals(checkingAccount.getSeeAlso().size(), 1); } catch (AtlasBaseException e) { fail("RelatedTerm association should've succeeded", e); } @@ -557,26 +639,16 @@ public class GlossaryServiceTest { adjustableRateMortgage.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm))); try { - AtlasGlossaryTerm updatedTerm = glossaryService.updateTerm(adjustableRateMortgage); - assertNotNull(updatedTerm.getSeeAlso()); - assertEquals(updatedTerm.getSeeAlso().size(), 1); + adjustableRateMortgage = glossaryService.updateTerm(adjustableRateMortgage); + assertNotNull(adjustableRateMortgage.getSeeAlso()); + assertEquals(adjustableRateMortgage.getSeeAlso().size(), 1); } catch (AtlasBaseException e) { fail("RelatedTerm association should've succeeded", e); } } - @DataProvider - public static Object[][] getGlossaryTermsProvider() { - return new Object[][]{ - // offset, limit, expected - {0, -1, 4}, - {0, 2, 2}, - {2, 5, 2}, - }; - } - - @Test(dataProvider = "getGlossaryTermsProvider", groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") + @Test(dataProvider = "getGlossaryTermsProvider" , groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") public void testGetGlossaryTerms(int offset, int limit, int expected) { String guid = bankGlossary.getGuid(); SortOrder sortOrder = SortOrder.ASCENDING; @@ -600,7 +672,7 @@ public class GlossaryServiceTest { }; } - @Test(dataProvider = "getGlossaryCategoriesProvider", groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") + @Test(dataProvider = "getGlossaryCategoriesProvider" , groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") public void testGetGlossaryCategories(int offset, int limit, int expected) { String guid = bankGlossary.getGuid(); SortOrder sortOrder = SortOrder.ASCENDING; @@ -626,7 +698,7 @@ public class GlossaryServiceTest { } - @Test(dataProvider = "getCategoryTermsProvider", groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE") + @Test(dataProvider = "getCategoryTermsProvider", dependsOnGroups = "Glossary.CREATE") public void testGetCategoryTerms(int offset, int limit, int expected) { for (AtlasGlossaryCategory c : Arrays.asList(accountCategory, mortgageCategory)) { try { http://git-wip-us.apache.org/repos/asf/atlas/blob/0dad9529/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 6779dee..f0c5d86 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 @@ -26,7 +26,7 @@ import org.apache.atlas.model.glossary.AtlasGlossaryCategory; import org.apache.atlas.model.glossary.AtlasGlossaryTerm; import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; -import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.AtlasRelatedObjectId; import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.atlas.web.util.Servlets; import org.apache.commons.collections.MapUtils; @@ -723,10 +723,10 @@ public class GlossaryREST { */ @GET @Path("/terms/{termGuid}/assignedEntities") - public List<AtlasEntityHeader> getEntitiesAssignedWithTerm(@PathParam("termGuid") String termGuid, - @DefaultValue("-1") @QueryParam("limit") String limit, - @DefaultValue("0") @QueryParam("offset") String offset, - @DefaultValue("ASC") @QueryParam("sort") final String sort) throws AtlasBaseException { + public List<AtlasRelatedObjectId> getEntitiesAssignedWithTerm(@PathParam("termGuid") String termGuid, + @DefaultValue("-1") @QueryParam("limit") String limit, + @DefaultValue("0") @QueryParam("offset") String offset, + @DefaultValue("ASC") @QueryParam("sort") final String sort) throws AtlasBaseException { Servlets.validateQueryParamLength("termGuid", termGuid); AtlasPerfTracer perf = null; @@ -746,7 +746,7 @@ public class GlossaryREST { /** * Assign the given term to the provided list of entity headers * @param termGuid Glossary term GUID - * @param entityHeaders Entity headers for which the term has to be associated + * @param relatedObjectIds Related Entity IDs to which the term has to be associated * @throws AtlasBaseException * @HTTP 204 If the term assignment was successful * @HTTP 400 If ANY of the entity header is invalid @@ -754,7 +754,7 @@ public class GlossaryREST { */ @POST @Path("/terms/{termGuid}/assignedEntities") - public void assignTermToEntities(@PathParam("termGuid") String termGuid, List<AtlasEntityHeader> entityHeaders) throws AtlasBaseException { + public void assignTermToEntities(@PathParam("termGuid") String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException { Servlets.validateQueryParamLength("termGuid", termGuid); AtlasPerfTracer perf = null; @@ -763,7 +763,7 @@ public class GlossaryREST { perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.assignTermToEntities(" + termGuid + ")"); } - glossaryService.assignTermToEntities(termGuid, entityHeaders); + glossaryService.assignTermToEntities(termGuid, relatedObjectIds); } finally { AtlasPerfTracer.log(perf); } @@ -772,7 +772,7 @@ public class GlossaryREST { /** * Remove the term assignment for the given list of entity headers * @param termGuid Glossary term GUID - * @param entityHeaders List of entity headers from which the term has to be dissociated + * @param relatedObjectIds List of related entity IDs from which the term has to be dissociated * @throws AtlasBaseException * @HTTP 204 If glossary term dissociation was successful * @HTTP 400 If ANY of the entity header is invalid @@ -780,7 +780,7 @@ public class GlossaryREST { */ @DELETE @Path("/terms/{termGuid}/assignedEntities") - public void removeTermAssignmentFromEntities(@PathParam("termGuid") String termGuid, List<AtlasEntityHeader> entityHeaders) throws AtlasBaseException { + public void removeTermAssignmentFromEntities(@PathParam("termGuid") String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException { Servlets.validateQueryParamLength("termGuid", termGuid); AtlasPerfTracer perf = null; @@ -789,7 +789,7 @@ public class GlossaryREST { perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.removeTermAssignmentFromEntities(" + termGuid + ")"); } - glossaryService.removeTermFromEntities(termGuid, entityHeaders); + glossaryService.removeTermFromEntities(termGuid, relatedObjectIds); } finally { AtlasPerfTracer.log(perf); }
