Commit 0dad9529 by apoorvnaik Committed by Madhan Neethiraj

ATLAS-2534: Glossary REST API implementation

Change-Id: I47210446be9e38c274bae0ee4a688187ba6e4fd0 Signed-off-by: 's avatarMadhan Neethiraj <madhan@apache.org>
parent 15967a93
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* * <p>
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* * <p>
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -28,10 +28,10 @@ public final class Constants { ...@@ -28,10 +28,10 @@ public final class Constants {
* Globally Unique identifier property key. * Globally Unique identifier property key.
*/ */
public static final String INTERNAL_PROPERTY_KEY_PREFIX = "__"; public static final String INTERNAL_PROPERTY_KEY_PREFIX = "__";
public static final String RELATIONSHIP_PROPERTY_KEY_PREFIX = "_r"; public static final String RELATIONSHIP_PROPERTY_KEY_PREFIX = "_r";
public static final String GUID_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "guid"; public static final String GUID_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "guid";
public static final String RELATIONSHIP_GUID_PROPERTY_KEY = RELATIONSHIP_PROPERTY_KEY_PREFIX + GUID_PROPERTY_KEY; public static final String RELATIONSHIP_GUID_PROPERTY_KEY = RELATIONSHIP_PROPERTY_KEY_PREFIX + GUID_PROPERTY_KEY;
/** /**
* Entity type name property key. * Entity type name property key.
...@@ -53,35 +53,35 @@ public final class Constants { ...@@ -53,35 +53,35 @@ public final class Constants {
/** /**
* Properties for type store graph. * Properties for type store graph.
*/ */
public static final String TYPE_CATEGORY_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.category"; public static final String TYPE_CATEGORY_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.category";
public static final String VERTEX_TYPE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type"; public static final String VERTEX_TYPE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type";
public static final String TYPENAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.name"; public static final String TYPENAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.name";
public static final String TYPEDESCRIPTION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.description"; public static final String TYPEDESCRIPTION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.description";
public static final String TYPEVERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.version"; public static final String TYPEVERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.version";
public static final String TYPEOPTIONS_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.options"; public static final String TYPEOPTIONS_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.options";
// relationship def constants // relationship def constants
public static final String RELATIONSHIPTYPE_END1_KEY = "endDef1"; public static final String RELATIONSHIPTYPE_END1_KEY = "endDef1";
public static final String RELATIONSHIPTYPE_END2_KEY = "endDef2"; public static final String RELATIONSHIPTYPE_END2_KEY = "endDef2";
public static final String RELATIONSHIPTYPE_CATEGORY_KEY = "relationshipCategory"; public static final String RELATIONSHIPTYPE_CATEGORY_KEY = "relationshipCategory";
public static final String RELATIONSHIPTYPE_TAG_PROPAGATION_KEY = "tagPropagation"; public static final String RELATIONSHIPTYPE_TAG_PROPAGATION_KEY = "tagPropagation";
public static final String RELATIONSHIPTYPE_BLOCKED_PROPAGATED_CLASSIFICATIONS_KEY = "blockedPropagatedClassifications"; public static final String RELATIONSHIPTYPE_BLOCKED_PROPAGATED_CLASSIFICATIONS_KEY = "blockedPropagatedClassifications";
/** /**
* Trait names property key and index name. * Trait names property key and index name.
*/ */
public static final String TRAIT_NAMES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "traitNames"; public static final String TRAIT_NAMES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "traitNames";
public static final String PROPAGATED_TRAIT_NAMES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "propagatedTraitNames"; public static final String PROPAGATED_TRAIT_NAMES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "propagatedTraitNames";
public static final String VERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "version"; public static final String VERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "version";
public static final String STATE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "state"; public static final String STATE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "state";
public static final String CREATED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "createdBy"; public static final String CREATED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "createdBy";
public static final String MODIFIED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "modifiedBy"; public static final String MODIFIED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "modifiedBy";
public static final String TIMESTAMP_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "timestamp"; public static final String TIMESTAMP_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "timestamp";
public static final String MODIFICATION_TIMESTAMP_PROPERTY_KEY = public static final String MODIFICATION_TIMESTAMP_PROPERTY_KEY =
INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp"; INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp";
/** /**
* search backing index name. * search backing index name.
...@@ -100,23 +100,23 @@ public final class Constants { ...@@ -100,23 +100,23 @@ public final class Constants {
public static final String FULLTEXT_INDEX = "fulltext_index"; public static final String FULLTEXT_INDEX = "fulltext_index";
public static final String QUALIFIED_NAME = "Referenceable.qualifiedName"; public static final String QUALIFIED_NAME = "Referenceable.qualifiedName";
public static final String TYPE_NAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "typeName"; public static final String TYPE_NAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "typeName";
public static final String INDEX_SEARCH_MAX_RESULT_SET_SIZE = "atlas.graph.index.search.max-result-set-size"; public static final String INDEX_SEARCH_MAX_RESULT_SET_SIZE = "atlas.graph.index.search.max-result-set-size";
public static final String INDEX_SEARCH_TYPES_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.types.max-query-str-length"; public static final String INDEX_SEARCH_TYPES_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.types.max-query-str-length";
public static final String INDEX_SEARCH_TAGS_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.tags.max-query-str-length"; public static final String INDEX_SEARCH_TAGS_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.tags.max-query-str-length";
public static final String INDEX_SEARCH_VERTEX_PREFIX_PROPERTY = "atlas.graph.index.search.vertex.prefix"; public static final String INDEX_SEARCH_VERTEX_PREFIX_PROPERTY = "atlas.graph.index.search.vertex.prefix";
public static final String INDEX_SEARCH_VERTEX_PREFIX_DEFAULT = "$v$"; public static final String INDEX_SEARCH_VERTEX_PREFIX_DEFAULT = "$v$";
public static final String MAX_FULLTEXT_QUERY_STR_LENGTH = "atlas.graph.fulltext-max-query-str-length"; public static final String MAX_FULLTEXT_QUERY_STR_LENGTH = "atlas.graph.fulltext-max-query-str-length";
public static final String MAX_DSL_QUERY_STR_LENGTH = "atlas.graph.dsl-max-query-str-length"; public static final String MAX_DSL_QUERY_STR_LENGTH = "atlas.graph.dsl-max-query-str-length";
public static final String ATTRIBUTE_NAME_GUID = "guid"; public static final String ATTRIBUTE_NAME_GUID = "guid";
public static final String ATTRIBUTE_NAME_TYPENAME = "typeName"; public static final String ATTRIBUTE_NAME_TYPENAME = "typeName";
public static final String ATTRIBUTE_NAME_SUPERTYPENAMES = "superTypeNames"; public static final String ATTRIBUTE_NAME_SUPERTYPENAMES = "superTypeNames";
public static final String ATTRIBUTE_NAME_STATE = "state"; public static final String ATTRIBUTE_NAME_STATE = "state";
public static final String ATTRIBUTE_NAME_VERSION = "version"; public static final String ATTRIBUTE_NAME_VERSION = "version";
public static final String TEMP_STRUCT_NAME_PREFIX = "__tempQueryResultStruct"; public static final String TEMP_STRUCT_NAME_PREFIX = "__tempQueryResultStruct";
public static final String CLASSIFICATION_ENTITY_GUID = INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid"; public static final String CLASSIFICATION_ENTITY_GUID = INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid";
public static final String CLASSIFICATION_VALIDITY_PERIODS_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "validityPeriods"; public static final String CLASSIFICATION_VALIDITY_PERIODS_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "validityPeriods";
...@@ -126,9 +126,10 @@ public final class Constants { ...@@ -126,9 +126,10 @@ public final class Constants {
public static final String CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "isPropagated"; public static final String CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "isPropagated";
public static final String CLASSIFICATION_EDGE_STATE_PROPERTY_KEY = STATE_PROPERTY_KEY; public static final String CLASSIFICATION_EDGE_STATE_PROPERTY_KEY = STATE_PROPERTY_KEY;
public static final String CLASSIFICATION_LABEL = "classifiedAs"; public static final String CLASSIFICATION_LABEL = "classifiedAs";
public static final String TERM_ASSIGNMENT_LABEL = "r:__AtlasGlossarySemanticAssignment";
public static final String VERTEX_ID_IN_IMPORT_KEY = "__vIdInImport"; public static final String VERTEX_ID_IN_IMPORT_KEY = "__vIdInImport";
public static final String EDGE_ID_IN_IMPORT_KEY = "__eIdInImport"; public static final String EDGE_ID_IN_IMPORT_KEY = "__eIdInImport";
private Constants() { private Constants() {
} }
......
...@@ -128,9 +128,16 @@ public enum AtlasErrorCode { ...@@ -128,9 +128,16 @@ public enum AtlasErrorCode {
NO_CLASSIFICATIONS_FOUND_FOR_ENTITY(400, "ATLAS-400-00-06E", "No classifications associated with entity: {0}"), NO_CLASSIFICATIONS_FOUND_FOR_ENTITY(400, "ATLAS-400-00-06E", "No classifications associated with entity: {0}"),
INVALID_CLASSIFICATION_PARAMS(400, "ATLAS-400-00-06F", "Invalid classification parameters passed for {0} operation for entity: {1}"), INVALID_CLASSIFICATION_PARAMS(400, "ATLAS-400-00-06F", "Invalid classification parameters passed for {0} operation for entity: {1}"),
PROPAGATED_CLASSIFICATION_NOT_ASSOCIATED_WITH_ENTITY(400, "ATLAS-400-00-070", "Propagated classification {0} is not associated with entity"), PROPAGATED_CLASSIFICATION_NOT_ASSOCIATED_WITH_ENTITY(400, "ATLAS-400-00-070", "Propagated classification {0} is not associated with entity"),
INVALID_PARTIAL_UPDATE_ATTR_VAL(400, "ATLAS-400-00-071", "Invalid attrVal for partial update of {0}, expected = {1} found {2}"), INVALID_BLOCKED_PROPAGATED_CLASSIFICATION(400, "ATLAS-400-00-071", "Invalid propagated classification: {0} with entityGuid: {1} added to blocked propagated classifications."),
MISSING_MANDATORY_ANCHOR(400, "ATLAS-400-00-072", "Mandatory anchor attribute is missing"), MISSING_MANDATORY_ANCHOR(400, "ATLAS-400-00-072", "Mandatory anchor attribute is missing"),
INVALID_BLOCKED_PROPAGATED_CLASSIFICATION(400, "ATLAS-400-00-073", "Invalid propagated classification: {0} with entityGuid: {1} added to blocked propagated classifications."), MISSING_MANDATORY_QUALIFIED_NAME(400, "ATLAS-400-00-073", "Mandatory qualifiedName attribute is missing"),
INVALID_PARTIAL_UPDATE_ATTR_VAL(400, "ATLAS-400-00-074", "Invalid attrVal for partial update of {0}, expected = {1} found {2}"),
MISSING_TERM_ID_FOR_CATEGORIZATION(400, "ATLAS-400-00-075", "Term guid can't be empty/null when adding to a category"),
INVALID_NEW_ANCHOR_GUID(400, "ATLAS-400-00-076", "New Anchor guid can't be empty/null"),
TERM_DISSOCIATION_MISSING_RELATION_GUID(400, "ATLAS-400-00-077", "Missing mandatory attribute, TermAssignment relationship guid"),
GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-078", "Attributes qualifiedName and displayName are missing. Failed to derive a unique name for Glossary"),
GLOSSARY_TERM_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-079", "Attributes qualifiedName, displayName & glossary name are missing. Failed to derive a unique name for Glossary term"),
GLOSSARY_CATEGORY_QUALIFIED_NAME_CANT_BE_DERIVED(400, "ATLAS-400-00-07A", "Attributes qualifiedName, displayName & glossary name are missing. Failed to derive a unique name for Glossary category"),
UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"), UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"),
......
...@@ -23,7 +23,7 @@ import org.apache.atlas.model.annotation.AtlasJSON; ...@@ -23,7 +23,7 @@ import org.apache.atlas.model.annotation.AtlasJSON;
import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader; import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasRelatedObjectId;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import java.util.HashMap; import java.util.HashMap;
...@@ -42,7 +42,7 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject { ...@@ -42,7 +42,7 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject {
// Attributes derived from relationships // Attributes derived from relationships
private AtlasGlossaryHeader anchor; private AtlasGlossaryHeader anchor;
private Set<AtlasEntityHeader> assignedEntities; private Set<AtlasRelatedObjectId> assignedEntities;
private Set<AtlasTermCategorizationHeader> categories; private Set<AtlasTermCategorizationHeader> categories;
// Related Terms // Related Terms
...@@ -128,21 +128,21 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject { ...@@ -128,21 +128,21 @@ public class AtlasGlossaryTerm extends AtlasGlossaryBaseObject {
setCategories(categories); setCategories(categories);
} }
public Set<AtlasEntityHeader> getAssignedEntities() { public Set<AtlasRelatedObjectId> getAssignedEntities() {
return assignedEntities; return assignedEntities;
} }
public void setAssignedEntities(final Set<AtlasEntityHeader> assignedEntities) { public void setAssignedEntities(final Set<AtlasRelatedObjectId> assignedEntities) {
this.assignedEntities = assignedEntities; this.assignedEntities = assignedEntities;
} }
public void addAssignedEntity(final AtlasEntityHeader entityHeader) { public void addAssignedEntity(final AtlasRelatedObjectId atlasObjectId) {
Set<AtlasEntityHeader> entityHeaders = this.assignedEntities; Set<AtlasRelatedObjectId> assignedEntities = this.assignedEntities;
if (entityHeaders == null) { if (assignedEntities == null) {
entityHeaders = new HashSet<>(); assignedEntities = new HashSet<>();
} }
entityHeaders.add(entityHeader); assignedEntities.add(atlasObjectId);
setAssignedEntities(entityHeaders); setAssignedEntities(assignedEntities);
} }
public Set<AtlasRelatedTermHeader> getSeeAlso() { public Set<AtlasRelatedTermHeader> getSeeAlso() {
......
...@@ -24,6 +24,7 @@ import java.util.Objects; ...@@ -24,6 +24,7 @@ import java.util.Objects;
@AtlasJSON @AtlasJSON
public class AtlasRelatedCategoryHeader { public class AtlasRelatedCategoryHeader {
private String categoryGuid; private String categoryGuid;
private String parentCategoryGuid;
private String relationGuid; private String relationGuid;
private String displayText; private String displayText;
private String description; private String description;
...@@ -61,6 +62,7 @@ public class AtlasRelatedCategoryHeader { ...@@ -61,6 +62,7 @@ public class AtlasRelatedCategoryHeader {
if (!(o instanceof AtlasRelatedCategoryHeader)) return false; if (!(o instanceof AtlasRelatedCategoryHeader)) return false;
final AtlasRelatedCategoryHeader that = (AtlasRelatedCategoryHeader) o; final AtlasRelatedCategoryHeader that = (AtlasRelatedCategoryHeader) o;
return Objects.equals(categoryGuid, that.categoryGuid) && return Objects.equals(categoryGuid, that.categoryGuid) &&
Objects.equals(parentCategoryGuid, that.parentCategoryGuid) &&
Objects.equals(displayText, that.displayText) && Objects.equals(displayText, that.displayText) &&
Objects.equals(description, that.description); Objects.equals(description, that.description);
} }
...@@ -68,13 +70,14 @@ public class AtlasRelatedCategoryHeader { ...@@ -68,13 +70,14 @@ public class AtlasRelatedCategoryHeader {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(categoryGuid, displayText, description); return Objects.hash(categoryGuid, parentCategoryGuid, displayText, description);
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder("AtlasRelatedCategoryId{"); final StringBuilder sb = new StringBuilder("AtlasRelatedCategoryId{");
sb.append("categoryGuid='").append(categoryGuid).append('\''); sb.append("categoryGuid='").append(categoryGuid).append('\'');
sb.append(", parentCategoryGuid='").append(parentCategoryGuid).append('\'');
sb.append(", relationGuid='").append(relationGuid).append('\''); sb.append(", relationGuid='").append(relationGuid).append('\'');
sb.append(", displayText='").append(displayText).append('\''); sb.append(", displayText='").append(displayText).append('\'');
sb.append(", description='").append(description).append('\''); sb.append(", description='").append(description).append('\'');
...@@ -90,4 +93,12 @@ public class AtlasRelatedCategoryHeader { ...@@ -90,4 +93,12 @@ public class AtlasRelatedCategoryHeader {
public void setRelationGuid(final String relationGuid) { public void setRelationGuid(final String relationGuid) {
this.relationGuid = relationGuid; this.relationGuid = relationGuid;
} }
public String getParentCategoryGuid() {
return parentCategoryGuid;
}
public void setParentCategoryGuid(final String parentCategoryGuid) {
this.parentCategoryGuid = parentCategoryGuid;
}
} }
...@@ -475,7 +475,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService { ...@@ -475,7 +475,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
AtlasObjectId objId = (AtlasObjectId) attrValue; AtlasObjectId objId = (AtlasObjectId) attrValue;
if (ret.getReferredEntities() == null) { if (ret.getReferredEntities() == null) {
ret.setReferredEntities(new HashMap<String, AtlasEntityHeader>()); ret.setReferredEntities(new HashMap<>());
} }
if (!ret.getReferredEntities().containsKey(objId.getGuid())) { if (!ret.getReferredEntities().containsKey(objId.getGuid())) {
...@@ -489,7 +489,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService { ...@@ -489,7 +489,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
AtlasObjectId objId = (AtlasObjectId) obj; AtlasObjectId objId = (AtlasObjectId) obj;
if (ret.getReferredEntities() == null) { if (ret.getReferredEntities() == null) {
ret.setReferredEntities(new HashMap<String, AtlasEntityHeader>()); ret.setReferredEntities(new HashMap<>());
} }
if (!ret.getReferredEntities().containsKey(objId.getGuid())) { if (!ret.getReferredEntities().containsKey(objId.getGuid())) {
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.glossary;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.type.AtlasRelationshipType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public class GlossaryCategoryUtils extends GlossaryUtils {
private static final Logger LOG = LoggerFactory.getLogger(GlossaryCategoryUtils.class);
private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
protected GlossaryCategoryUtils(AtlasRelationshipStore relationshipStore, AtlasTypeRegistry typeRegistry) {
super(relationshipStore, typeRegistry);
}
public void processCategoryRelations(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException {
if (DEBUG_ENABLED) {
LOG.debug("==> GlossaryCategoryUtils.processCategoryRelations({}, {}, {})", updatedCategory, existing, op);
}
processCategoryAnchor(updatedCategory, existing, op);
processParentCategory(updatedCategory, existing, op);
processCategoryChildren(updatedCategory, existing, op);
processAssociatedTerms(updatedCategory, existing, op);
if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryCategoryUtils.processCategoryRelations()");
}
}
private void processCategoryAnchor(AtlasGlossaryCategory updatedCategory, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException {
if (Objects.isNull(updatedCategory.getAnchor()) && op != RelationshipOperation.DELETE) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
}
switch (op) {
case CREATE:
if (DEBUG_ENABLED) {
LOG.debug("Creating new category anchor, category = {}, glossary = {}", existing.getGuid(), updatedCategory.getAnchor().getDisplayText());
}
String anchorGlossaryGuid = updatedCategory.getAnchor().getGlossaryGuid();
createRelationship(defineCategoryAnchorRelation(anchorGlossaryGuid, existing.getGuid()));
break;
case UPDATE:
if (!Objects.equals(updatedCategory.getAnchor(), existing.getAnchor())) {
if (Objects.isNull(updatedCategory.getAnchor().getGlossaryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_NEW_ANCHOR_GUID);
}
if (DEBUG_ENABLED) {
LOG.debug("Updating category anchor, category = {}, currAnchor = {}, newAnchor = {}", existing.getGuid(),
existing.getAnchor().getDisplayText(), updatedCategory.getAnchor().getDisplayText());
}
relationshipStore.deleteById(existing.getAnchor().getRelationGuid());
createRelationship(defineCategoryAnchorRelation(updatedCategory.getAnchor().getGlossaryGuid(), existing.getGuid()));
}
break;
case DELETE:
if (Objects.nonNull(existing.getAnchor())) {
if (DEBUG_ENABLED) {
LOG.debug("Deleting category anchor");
}
relationshipStore.deleteById(existing.getAnchor().getRelationGuid());
}
break;
}
}
private void processParentCategory(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException {
AtlasRelatedCategoryHeader newParent = newObj.getParentCategory();
AtlasRelatedCategoryHeader existingParent = existing.getParentCategory();
switch (op) {
case CREATE:
if (Objects.nonNull(newParent)) {
if (DEBUG_ENABLED) {
LOG.debug("Creating new parent, category = {}, parent = {}", existing.getGuid(), newParent.getDisplayText());
}
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
}
break;
case UPDATE:
if (Objects.equals(newParent, existingParent)) {
if (DEBUG_ENABLED) {
LOG.debug("No change to parent");
}
break;
}
if (Objects.isNull(existingParent)) {
if (DEBUG_ENABLED) {
LOG.debug("Creating new parent, category = {}, parent = {}", existing.getGuid(), newParent.getDisplayText());
}
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
} else if (Objects.isNull(newParent)) {
if (DEBUG_ENABLED) {
LOG.debug("Removing category parent, category = {}, parent = {}", existing.getGuid(), existingParent.getDisplayText());
}
relationshipStore.deleteById(existingParent.getRelationGuid());
} else {
if (DEBUG_ENABLED) {
LOG.debug("Updating category parent, category = {}, currParent = {}, newParent = {}", existing.getGuid(), existingParent.getDisplayText(), newParent.getDisplayText());
}
AtlasRelationship parentRelationship = relationshipStore.getById(existingParent.getRelationGuid());
if (existingParent.getCategoryGuid().equals(newParent.getCategoryGuid())) {
updateRelationshipAttributes(parentRelationship, newParent);
relationshipStore.update(parentRelationship);
} else {
// Delete link to existing parent and link to new parent
relationshipStore.deleteById(parentRelationship.getGuid());
createRelationship(defineCategoryHierarchyLink(newParent, existing.getGuid()));
}
}
break;
case DELETE:
if (Objects.nonNull(existingParent)) {
if (DEBUG_ENABLED) {
LOG.debug("Removing category parent, category = {}, parent = {}", existing.getGuid(), existingParent.getDisplayText());
}
relationshipStore.deleteById(existingParent.getRelationGuid());
}
break;
}
}
private void processAssociatedTerms(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException {
Set<AtlasRelatedTermHeader> newTerms = newObj.getTerms();
Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
switch (op) {
case CREATE:
if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(),
Objects.nonNull(newTerms) ? newTerms.size() : "none");
}
createTermCategorizationRelationships(existing, newTerms);
break;
case UPDATE:
if (CollectionUtils.isEmpty(existingTerms)) {
if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(),
Objects.nonNull(newTerms) ? newTerms.size() : "none");
}
createTermCategorizationRelationships(existing, newTerms);
break;
}
if (CollectionUtils.isEmpty(newTerms)) {
if (DEBUG_ENABLED) {
LOG.debug("Deleting term relation with category = {}, terms = {}", existing.getDisplayName(), existingTerms.size());
}
deleteTermCategorizationRelationships(existing, existingTerms);
break;
}
Set<AtlasRelatedTermHeader> toCreate = newTerms
.stream()
.filter(c -> Objects.isNull(c.getRelationGuid()))
.collect(Collectors.toSet());
createTermCategorizationRelationships(existing, toCreate);
Set<AtlasRelatedTermHeader> toUpdate = newTerms
.stream()
.filter(c -> Objects.nonNull(c.getRelationGuid()) && existingTerms.contains(c))
.collect(Collectors.toSet());
updateTermCategorizationRelationships(existing, toUpdate);
Set<AtlasRelatedTermHeader> toDelete = existingTerms
.stream()
.filter(c -> !toCreate.contains(c) && !toUpdate.contains(c))
.collect(Collectors.toSet());
deleteTermCategorizationRelationships(existing, toDelete);
break;
case DELETE:
deleteTermCategorizationRelationships(existing, existingTerms);
break;
}
}
private void createTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) {
Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
for (AtlasRelatedTermHeader term : terms) {
if (Objects.isNull(term.getTermGuid())) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_TERM_ID_FOR_CATEGORIZATION);
} else {
if (Objects.nonNull(existingTerms) && existingTerms.contains(term)) {
if (DEBUG_ENABLED) {
LOG.debug("Skipping existing term guid={}", term.getTermGuid());
}
continue;
}
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between category = {} and term = {}", existing.getGuid(), term.getDisplayText());
}
createRelationship(defineCategorizedTerm(existing.getGuid(), term));
}
}
}
}
private void updateTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) {
for (AtlasRelatedTermHeader term : terms) {
if (DEBUG_ENABLED) {
LOG.debug("Updating term relation with category = {}, term = {}", existing.getDisplayName(), term.getDisplayText());
}
AtlasRelationship relationship = relationshipStore.getById(term.getRelationGuid());
updateRelationshipAttributes(relationship, term);
relationshipStore.update(relationship);
}
}
}
private void deleteTermCategorizationRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(terms)) {
for (AtlasRelatedTermHeader term : terms) {
if (DEBUG_ENABLED) {
LOG.debug("Creating term relation with category = {}, terms = {}", existing.getDisplayName(), term.getDisplayText());
}
relationshipStore.deleteById(term.getRelationGuid());
}
}
}
private void processCategoryChildren(AtlasGlossaryCategory newObj, AtlasGlossaryCategory existing, RelationshipOperation op) throws AtlasBaseException {
Set<AtlasRelatedCategoryHeader> newChildren = newObj.getChildrenCategories();
Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories();
switch (op) {
case CREATE:
if (DEBUG_ENABLED) {
LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(),
Objects.nonNull(newChildren) ? newChildren.size() : "none");
}
createCategoryRelationships(existing, newChildren);
break;
case UPDATE:
// Create new children
if (CollectionUtils.isEmpty(existingChildren)) {
if (DEBUG_ENABLED) {
LOG.debug("Creating new children, category = {}, children = {}", existing.getDisplayName(),
Objects.nonNull(newChildren) ? newChildren.size() : "none");
}
createCategoryRelationships(existing, newChildren);
break;
}
// Delete current children
if (CollectionUtils.isEmpty(newChildren)) {
if (DEBUG_ENABLED) {
LOG.debug("Deleting children, category = {}, children = {}", existing.getDisplayName(), existingChildren.size());
}
deleteCategoryRelationships(existing, existingChildren);
break;
}
Set<AtlasRelatedCategoryHeader> toCreate = newChildren
.stream()
.filter(c -> Objects.isNull(c.getRelationGuid()))
.collect(Collectors.toSet());
createCategoryRelationships(existing, toCreate);
Set<AtlasRelatedCategoryHeader> toUpdate = newChildren
.stream()
.filter(c -> Objects.nonNull(c.getRelationGuid()) && existingChildren.contains(c))
.collect(Collectors.toSet());
updateCategoryRelationships(existing, toUpdate);
Set<AtlasRelatedCategoryHeader> toDelete = existingChildren
.stream()
.filter(c -> !toCreate.contains(c) && !toUpdate.contains(c))
.collect(Collectors.toSet());
deleteCategoryRelationships(existing, toDelete);
break;
case DELETE:
deleteCategoryRelationships(existing, existingChildren);
break;
}
}
private void createCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> newChildren) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(newChildren)) {
Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories();
for (AtlasRelatedCategoryHeader child : newChildren) {
if (Objects.nonNull(existingChildren) && existingChildren.contains(child)) {
if (DEBUG_ENABLED) {
LOG.debug("Skipping existing child relation for category guid = {}", child.getCategoryGuid());
}
continue;
}
if (DEBUG_ENABLED) {
LOG.debug("Creating new child, category = {}, child = {}", existing.getDisplayName(), child.getDisplayText());
}
createRelationship(defineCategoryHierarchyLink(existing.getGuid(), child));
}
}
}
private void updateCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> toUpdate) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(toUpdate)) {
for (AtlasRelatedCategoryHeader categoryHeader : toUpdate) {
if (DEBUG_ENABLED) {
LOG.debug("Updating child, category = {}, child = {}", existing.getDisplayName(), categoryHeader.getDisplayText());
}
AtlasRelationship childRelationship = relationshipStore.getById(categoryHeader.getRelationGuid());
updateRelationshipAttributes(childRelationship, categoryHeader);
relationshipStore.update(childRelationship);
}
}
}
private void deleteCategoryRelationships(AtlasGlossaryCategory existing, Set<AtlasRelatedCategoryHeader> existingChildren) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(existingChildren)) {
for (AtlasRelatedCategoryHeader child : existingChildren) {
if (DEBUG_ENABLED) {
LOG.debug("Deleting child, category = {}, child = {}", existing.getDisplayName(), child.getDisplayText());
}
relationshipStore.deleteById(child.getRelationGuid());
}
}
}
private AtlasRelationship defineCategoryAnchorRelation(String glossaryGuid, String categoryGuid) {
AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(CATEGORY_ANCHOR);
AtlasStruct defaultAttrs = relationshipType.createDefaultValue();
return new AtlasRelationship(CATEGORY_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(categoryGuid), defaultAttrs.getAttributes());
}
private AtlasRelationship defineCategoryHierarchyLink(String parentCategoryGuid, AtlasRelatedCategoryHeader childCategory) {
AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(CATEGORY_HIERARCHY);
AtlasStruct defaultAttrs = relationshipType.createDefaultValue();
AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategoryGuid), new AtlasObjectId(childCategory.getCategoryGuid()), defaultAttrs.getAttributes());
updateRelationshipAttributes(relationship, childCategory);
return relationship;
}
private AtlasRelationship defineCategoryHierarchyLink(AtlasRelatedCategoryHeader parentCategory, String childGuid) {
AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(CATEGORY_HIERARCHY);
AtlasStruct defaultAttrs = relationshipType.createDefaultValue();
AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategory.getCategoryGuid()), new AtlasObjectId(childGuid), defaultAttrs.getAttributes());
updateRelationshipAttributes(relationship, parentCategory);
return relationship;
}
private AtlasRelationship defineCategorizedTerm(String categoryGuid, AtlasRelatedTermHeader relatedTermId) {
AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(TERM_CATEGORIZATION);
AtlasStruct defaultAttrs = relationshipType.createDefaultValue();
AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(categoryGuid), new AtlasObjectId(relatedTermId.getTermGuid()), defaultAttrs.getAttributes());
updateRelationshipAttributes(relationship, relatedTermId);
return relationship;
}
private void updateRelationshipAttributes(AtlasRelationship relationship, AtlasRelatedCategoryHeader relatedCategoryHeader) {
if (Objects.nonNull(relationship)) {
relationship.setAttribute("description", relatedCategoryHeader.getDescription());
}
}
}
...@@ -26,13 +26,13 @@ import org.apache.atlas.model.glossary.AtlasGlossaryTerm; ...@@ -26,13 +26,13 @@ import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader; import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasRelatedObjectId;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.repository.ogm.DataAccess; import org.apache.atlas.repository.ogm.DataAccess;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1; import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -53,24 +53,17 @@ public class GlossaryService { ...@@ -53,24 +53,17 @@ public class GlossaryService {
private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class); private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class);
private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled(); private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
private static final String ATLAS_GLOSSARY_PREFIX = "__AtlasGlossary";
// Relation name constants
private static final String TERM_ANCHOR = ATLAS_GLOSSARY_PREFIX + "TermAnchor";
private static final String CATEGORY_ANCHOR = ATLAS_GLOSSARY_PREFIX + "CategoryAnchor";
private static final String CATEGORY_HIERARCHY = ATLAS_GLOSSARY_PREFIX + "CategoryHierarchyLink";
private static final String TERM_CATEGORIZATION = ATLAS_GLOSSARY_PREFIX + "TermCategorization";
private static final String TERM_ASSIGNMENT = ATLAS_GLOSSARY_PREFIX + "SemanticAssignment";
private final DataAccess dataAccess; private final DataAccess dataAccess;
private final AtlasRelationshipStore relationshipStore; private final GlossaryTermUtils glossaryTermUtils;
private final GlossaryCategoryUtils glossaryCategoryUtils;
@Inject @Inject
public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore relationshipStore) { public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore relationshipStore, final AtlasTypeRegistry typeRegistry) {
this.dataAccess = dataAccess; this.dataAccess = dataAccess;
this.relationshipStore = relationshipStore; glossaryTermUtils = new GlossaryTermUtils(relationshipStore, typeRegistry);
glossaryCategoryUtils = new GlossaryCategoryUtils(relationshipStore, typeRegistry);
} }
/** /**
* List all glossaries * List all glossaries
* *
...@@ -85,7 +78,7 @@ public class GlossaryService { ...@@ -85,7 +78,7 @@ public class GlossaryService {
LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, offset, sortOrder); LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, offset, sortOrder);
} }
List<String> glossaryGuids = AtlasGraphUtilsV1.findEntityGUIDsByType(ATLAS_GLOSSARY_PREFIX, sortOrder); List<String> glossaryGuids = AtlasGraphUtilsV1.findEntityGUIDsByType(GlossaryUtils.ATLAS_GLOSSARY_PREFIX, sortOrder);
PaginationHelper paginationHelper = new PaginationHelper<>(glossaryGuids, offset, limit); PaginationHelper paginationHelper = new PaginationHelper<>(glossaryGuids, offset, limit);
List<AtlasGlossary> ret; List<AtlasGlossary> ret;
...@@ -95,7 +88,11 @@ public class GlossaryService { ...@@ -95,7 +88,11 @@ public class GlossaryService {
Iterable<AtlasGlossary> glossaries = dataAccess.load(ret); Iterable<AtlasGlossary> glossaries = dataAccess.load(ret);
ret.clear(); ret.clear();
glossaries.forEach(ret::add); // Set the displayText for all relations
for (AtlasGlossary glossary : glossaries) {
setInfoForRelations(glossary);
ret.add(glossary);
}
} else { } else {
ret = Collections.emptyList(); ret = Collections.emptyList();
} }
...@@ -121,9 +118,12 @@ public class GlossaryService { ...@@ -121,9 +118,12 @@ public class GlossaryService {
if (Objects.isNull(atlasGlossary)) { if (Objects.isNull(atlasGlossary)) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary definition missing"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary definition missing");
} }
if (Objects.isNull(atlasGlossary.getQualifiedName())) { if (StringUtils.isEmpty(atlasGlossary.getQualifiedName())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary qualifiedName is mandatory"); if (StringUtils.isEmpty(atlasGlossary.getDisplayName())) {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_QUALIFIED_NAME_CANT_BE_DERIVED);
} else {
atlasGlossary.setQualifiedName(atlasGlossary.getDisplayName());
}
} }
AtlasGlossary saved = dataAccess.save(atlasGlossary); AtlasGlossary saved = dataAccess.save(atlasGlossary);
...@@ -152,7 +152,7 @@ public class GlossaryService { ...@@ -152,7 +152,7 @@ public class GlossaryService {
AtlasGlossary atlasGlossary = getGlossarySkeleton(glossaryGuid); AtlasGlossary atlasGlossary = getGlossarySkeleton(glossaryGuid);
AtlasGlossary ret = dataAccess.load(atlasGlossary); AtlasGlossary ret = dataAccess.load(atlasGlossary);
setDisplayTextForRelations(ret); setInfoForRelations(ret);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.getGlossary() : {}", ret); LOG.debug("<== GlossaryService.getGlossary() : {}", ret);
...@@ -219,10 +219,9 @@ public class GlossaryService { ...@@ -219,10 +219,9 @@ public class GlossaryService {
if (!ret.equals(atlasGlossary)) { if (!ret.equals(atlasGlossary)) {
atlasGlossary.setGuid(ret.getGuid()); atlasGlossary.setGuid(ret.getGuid());
atlasGlossary.setQualifiedName(ret.getQualifiedName());
ret = dataAccess.save(atlasGlossary); ret = dataAccess.save(atlasGlossary);
setDisplayTextForRelations(ret); setInfoForRelations(ret);
} }
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
...@@ -239,8 +238,15 @@ public class GlossaryService { ...@@ -239,8 +238,15 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
} }
AtlasGlossary existing = dataAccess.load(getGlossarySkeleton(glossaryGuid));
Set<AtlasRelatedTermHeader> terms = existing.getTerms();
deleteTerms(existing, terms);
// FIXME: When deleting all other related entities, the new edge label (r:<Relation>) is failing the delete calls Set<AtlasRelatedCategoryHeader> categories = existing.getCategories();
deleteCategories(existing, categories);
// Once all relations are deleted, then delete the Glossary
dataAccess.delete(glossaryGuid); dataAccess.delete(glossaryGuid);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
...@@ -263,7 +269,7 @@ public class GlossaryService { ...@@ -263,7 +269,7 @@ public class GlossaryService {
AtlasGlossaryTerm atlasGlossary = getAtlasGlossaryTermSkeleton(termGuid); AtlasGlossaryTerm atlasGlossary = getAtlasGlossaryTermSkeleton(termGuid);
AtlasGlossaryTerm ret = dataAccess.load(atlasGlossary); AtlasGlossaryTerm ret = dataAccess.load(atlasGlossary);
setDisplayTextForRelations(ret); setInfoForRelations(ret);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.getTerm() : {}", ret); LOG.debug("<== GlossaryService.getTerm() : {}", ret);
...@@ -278,24 +284,30 @@ public class GlossaryService { ...@@ -278,24 +284,30 @@ public class GlossaryService {
if (Objects.isNull(glossaryTerm)) { if (Objects.isNull(glossaryTerm)) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryTerm definition missing"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryTerm definition missing");
} }
if (Objects.isNull(glossaryTerm.getQualifiedName())) { if (Objects.isNull(glossaryTerm.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryTerm qualifiedName is mandatory"); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
}
if (StringUtils.isEmpty(glossaryTerm.getQualifiedName())) {
String displayName = glossaryTerm.getDisplayName();
String glossaryName = glossaryTerm.getAnchor().getDisplayText();
if (StringUtils.isEmpty(displayName) || StringUtils.isEmpty(glossaryName)) {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_TERM_QUALIFIED_NAME_CANT_BE_DERIVED);
} else {
glossaryTerm.setQualifiedName(displayName + "@" + glossaryName);
}
} }
AtlasGlossaryTerm saved = dataAccess.save(glossaryTerm); AtlasGlossaryTerm existing = dataAccess.save(glossaryTerm);
glossaryTermUtils.processTermRelations(glossaryTerm, existing, GlossaryUtils.RelationshipOperation.CREATE);
// TODO: Create all term relations
processTermAnchor(glossaryTerm, saved);
processRelatedTerms(glossaryTerm, saved);
processAssociatedCategories(glossaryTerm, saved);
saved = dataAccess.load(glossaryTerm); // Re-load term after handling relations
setDisplayTextForRelations(saved); existing = dataAccess.load(glossaryTerm);
setInfoForRelations(existing);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.create() : {}", saved); LOG.debug("<== GlossaryService.create() : {}", existing);
} }
return saved; return existing;
} }
public List<AtlasGlossaryTerm> createTerms(List<AtlasGlossaryTerm> glossaryTerm) throws AtlasBaseException { public List<AtlasGlossaryTerm> createTerms(List<AtlasGlossaryTerm> glossaryTerm) throws AtlasBaseException {
...@@ -340,14 +352,13 @@ public class GlossaryService { ...@@ -340,14 +352,13 @@ public class GlossaryService {
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
LOG.debug("Glossary term had no immediate attr updates. Exception: {}", e.getMessage()); LOG.debug("Glossary term had no immediate attr updates. Exception: {}", e.getMessage());
} finally { } finally {
// TODO: Manage remaining term relations glossaryTermUtils.processTermRelations(atlasGlossaryTerm, existing, GlossaryUtils.RelationshipOperation.UPDATE);
processRelations(atlasGlossaryTerm, existing);
} }
} }
updated = dataAccess.load(atlasGlossaryTerm); updated = dataAccess.load(atlasGlossaryTerm);
setDisplayTextForRelations(updated); setInfoForRelations(updated);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.updateTerm() : {}", updated); LOG.debug("<== GlossaryService.updateTerm() : {}", updated);
} }
...@@ -362,7 +373,15 @@ public class GlossaryService { ...@@ -362,7 +373,15 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
} }
AtlasGlossaryTerm existing = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
// Remove term from Glossary
glossaryTermUtils.processTermRelations(existing, existing, GlossaryUtils.RelationshipOperation.DELETE);
// Remove term associations with Entities
glossaryTermUtils.processTermDissociation(existing, existing.getAssignedEntities());
// Now delete the term
dataAccess.delete(termGuid); dataAccess.delete(termGuid);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
...@@ -370,35 +389,28 @@ public class GlossaryService { ...@@ -370,35 +389,28 @@ public class GlossaryService {
} }
} }
public void assignTermToEntities(String termGuid, Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException { public void assignTermToEntities(String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
if (DEBUG_ENABLED) {
LOG.debug("==> GlossaryService.assignTermToEntities({}, {})", termGuid, relatedObjectIds);
}
AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid)); AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
glossaryTermUtils.processTermAssignments(glossaryTerm, relatedObjectIds);
if (Objects.nonNull(glossaryTerm)) { if (DEBUG_ENABLED) {
Set<AtlasEntityHeader> assignedEntities = glossaryTerm.getAssignedEntities(); LOG.debug("<== GlossaryService.assignTermToEntities()");
for (AtlasEntityHeader entityHeader : entityHeaders) {
if (CollectionUtils.isNotEmpty(assignedEntities) && assignedEntities.contains(entityHeader)) continue;
if (DEBUG_ENABLED) {
LOG.debug("Assigning term guid={}, to entity guid = {}", termGuid, entityHeader.getGuid());
}
createRelationship(defineTermAssignment(termGuid, entityHeader));
}
} }
} }
public void removeTermFromEntities(String termGuid, Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException { public void removeTermFromEntities(String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("==> GlossaryService.removeTermFromEntities({}, {})", termGuid, relatedObjectIds);
}
AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid)); AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
glossaryTermUtils.processTermDissociation(glossaryTerm, relatedObjectIds);
if (Objects.nonNull(glossaryTerm)) { if (LOG.isDebugEnabled()) {
for (AtlasEntityHeader entityHeader : entityHeaders) { LOG.debug("<== GlossaryService.removeTermFromEntities()");
if (DEBUG_ENABLED) {
LOG.debug("Removing term guid={}, from entity guid = {}", termGuid, entityHeader.getGuid());
}
Object relationGuid = entityHeader.getAttribute("relationGuid");
if (Objects.isNull(relationGuid)) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "EntityHeader is missing mandatory attribute relation guid");
}
relationshipStore.deleteById((String) relationGuid);
}
} }
} }
...@@ -413,11 +425,10 @@ public class GlossaryService { ...@@ -413,11 +425,10 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "categoryGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "categoryGuid is null/empty");
} }
AtlasGlossaryCategory atlasGlossary = getAtlasGlossaryCategorySkeleton(categoryGuid); AtlasGlossaryCategory atlasGlossary = getAtlasGlossaryCategorySkeleton(categoryGuid);
AtlasGlossaryCategory ret = dataAccess.load(atlasGlossary); AtlasGlossaryCategory ret = dataAccess.load(atlasGlossary);
setDisplayTextForRelations(ret); setInfoForRelations(ret);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.getCategory() : {}", ret); LOG.debug("<== GlossaryService.getCategory() : {}", ret);
...@@ -433,28 +444,26 @@ public class GlossaryService { ...@@ -433,28 +444,26 @@ public class GlossaryService {
if (Objects.isNull(glossaryCategory)) { if (Objects.isNull(glossaryCategory)) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory definition missing"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory definition missing");
} }
if (Objects.isNull(glossaryCategory.getQualifiedName())) { if (Objects.isNull(glossaryCategory.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory qualifiedName is mandatory"); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ANCHOR);
}
if (StringUtils.isEmpty(glossaryCategory.getQualifiedName())) {
String displayName = glossaryCategory.getDisplayName();
String glossaryName = glossaryCategory.getAnchor().getDisplayText();
if (StringUtils.isEmpty(displayName) || StringUtils.isEmpty(glossaryName)) {
throw new AtlasBaseException(AtlasErrorCode.GLOSSARY_CATEGORY_QUALIFIED_NAME_CANT_BE_DERIVED);
} else {
glossaryCategory.setQualifiedName(displayName + "@" + glossaryName);
}
} }
AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory); AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory);
// Attempt relation creation // Attempt relation creation
if (Objects.nonNull(glossaryCategory.getAnchor())) { glossaryCategoryUtils.processCategoryRelations(glossaryCategory, saved, GlossaryUtils.RelationshipOperation.CREATE);
processCategoryAnchor(glossaryCategory, saved);
}
if (Objects.nonNull(glossaryCategory.getParentCategory())) {
processParentCategory(glossaryCategory, saved);
}
if (CollectionUtils.isNotEmpty(glossaryCategory.getChildrenCategories())) {
processCategoryChildren(glossaryCategory, saved);
}
saved = dataAccess.load(glossaryCategory); saved = dataAccess.load(glossaryCategory);
setDisplayTextForRelations(glossaryCategory); setInfoForRelations(glossaryCategory);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.createCategory() : {}", saved); LOG.debug("<== GlossaryService.createCategory() : {}", saved);
...@@ -502,7 +511,7 @@ public class GlossaryService { ...@@ -502,7 +511,7 @@ public class GlossaryService {
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
LOG.debug("No immediate attribute update. Exception: {}", e.getMessage()); LOG.debug("No immediate attribute update. Exception: {}", e.getMessage());
} finally { } finally {
processRelations(glossaryCategory, existing); glossaryCategoryUtils.processCategoryRelations(glossaryCategory, existing, GlossaryUtils.RelationshipOperation.UPDATE);
} }
} }
...@@ -511,7 +520,7 @@ public class GlossaryService { ...@@ -511,7 +520,7 @@ public class GlossaryService {
} }
ret = dataAccess.load(glossaryCategory); ret = dataAccess.load(glossaryCategory);
setDisplayTextForRelations(glossaryCategory); setInfoForRelations(glossaryCategory);
return ret; return ret;
} }
...@@ -524,12 +533,17 @@ public class GlossaryService { ...@@ -524,12 +533,17 @@ public class GlossaryService {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category guid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category guid is null/empty");
} }
AtlasGlossaryCategory existing = dataAccess.load(getAtlasGlossaryCategorySkeleton(categoryGuid));
// Delete all relations
glossaryCategoryUtils.processCategoryRelations(existing, existing, GlossaryUtils.RelationshipOperation.DELETE);
// Now delete the category
dataAccess.delete(categoryGuid); dataAccess.delete(categoryGuid);
if (DEBUG_ENABLED) { if (DEBUG_ENABLED) {
LOG.debug("<== GlossaryService.deleteCategory()"); LOG.debug("<== GlossaryService.deleteCategory()");
} }
} }
public List<AtlasGlossaryTerm> getGlossaryTerms(String glossaryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException { public List<AtlasGlossaryTerm> getGlossaryTerms(String glossaryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
...@@ -585,8 +599,8 @@ public class GlossaryService { ...@@ -585,8 +599,8 @@ public class GlossaryService {
if (CollectionUtils.isNotEmpty(categories)) { if (CollectionUtils.isNotEmpty(categories)) {
if (sortOrder != null) { if (sortOrder != null) {
categories.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ? categories.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
o1.getDisplayText().compareTo(o2.getDisplayText()) : o1.getDisplayText().compareTo(o2.getDisplayText()) :
o2.getDisplayText().compareTo(o1.getDisplayText())); o2.getDisplayText().compareTo(o1.getDisplayText()));
} }
ret = new PaginationHelper<>(categories, offset, limit).getPaginatedList(); ret = new PaginationHelper<>(categories, offset, limit).getPaginatedList();
} else { } else {
...@@ -615,8 +629,8 @@ public class GlossaryService { ...@@ -615,8 +629,8 @@ public class GlossaryService {
if (CollectionUtils.isNotEmpty(glossaryCategory.getTerms())) { if (CollectionUtils.isNotEmpty(glossaryCategory.getTerms())) {
if (sortOrder != null) { if (sortOrder != null) {
terms.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ? terms.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
o1.getDisplayText().compareTo(o2.getDisplayText()) : o1.getDisplayText().compareTo(o2.getDisplayText()) :
o2.getDisplayText().compareTo(o1.getDisplayText())); o2.getDisplayText().compareTo(o1.getDisplayText()));
} }
ret = new PaginationHelper<>(terms, offset, limit).getPaginatedList(); ret = new PaginationHelper<>(terms, offset, limit).getPaginatedList();
} else { } else {
...@@ -682,15 +696,15 @@ public class GlossaryService { ...@@ -682,15 +696,15 @@ public class GlossaryService {
return ret; return ret;
} }
public List<AtlasEntityHeader> getAssignedEntities(final String termGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException { public List<AtlasRelatedObjectId> getAssignedEntities(final String termGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
if (Objects.isNull(termGuid)) { if (Objects.isNull(termGuid)) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty"); throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
} }
AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid)); AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
Set<AtlasEntityHeader> assignedEntities = glossaryTerm.getAssignedEntities(); Set<AtlasRelatedObjectId> assignedEntities = glossaryTerm.getAssignedEntities();
List<AtlasEntityHeader> ret; List<AtlasRelatedObjectId> ret;
if (CollectionUtils.isNotEmpty(assignedEntities)) { if (CollectionUtils.isNotEmpty(assignedEntities)) {
ret = new ArrayList<>(assignedEntities); ret = new ArrayList<>(assignedEntities);
if (sortOrder != null) { if (sortOrder != null) {
...@@ -712,79 +726,69 @@ public class GlossaryService { ...@@ -712,79 +726,69 @@ public class GlossaryService {
return glossary; return glossary;
} }
private void processAssignedEntities(final AtlasGlossaryTerm newObj, final AtlasGlossaryTerm existing) throws AtlasBaseException { private void deleteCategories(final AtlasGlossary existing, final Set<AtlasRelatedCategoryHeader> categories) throws AtlasBaseException {
if (newObj.equals(existing)) return; if (CollectionUtils.isNotEmpty(categories)) {
if (DEBUG_ENABLED) {
LOG.debug("Deleting categories within glossary guid = {}", existing.getGuid());
}
for (AtlasRelatedCategoryHeader category : categories) {
// Delete category
deleteCategory(category.getCategoryGuid());
}
}
}
if (CollectionUtils.isNotEmpty(newObj.getAssignedEntities())) { private void deleteTerms(final AtlasGlossary existing, final Set<AtlasRelatedTermHeader> terms) throws AtlasBaseException {
for (AtlasEntityHeader entityHeader : newObj.getAssignedEntities()) { if (CollectionUtils.isNotEmpty(terms)) {
createRelationship(defineTermAssignment(existing.getGuid(), entityHeader)); if (DEBUG_ENABLED) {
LOG.debug("Deleting terms within glossary guid = {}", existing.getGuid());
}
for (AtlasRelatedTermHeader term : terms) {
// Delete the term
deleteTerm(term.getTermGuid());
} }
} }
} }
private void setDisplayTextForRelations(final AtlasGlossary ret) throws AtlasBaseException { private AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String termGuid) {
AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
glossaryTerm.setGuid(termGuid);
return glossaryTerm;
}
private AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final String categoryGuid) {
AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
glossaryCategory.setGuid(categoryGuid);
return glossaryCategory;
}
private void setInfoForRelations(final AtlasGlossary ret) throws AtlasBaseException {
if (Objects.nonNull(ret.getTerms())) { if (Objects.nonNull(ret.getTerms())) {
setDisplayNameForTerms(ret.getTerms()); setInfoForTerms(ret.getTerms());
} }
if (Objects.nonNull(ret.getCategories())) { if (Objects.nonNull(ret.getCategories())) {
setDisplayNameForRelatedCategories(ret.getCategories()); setInfoForRelatedCategories(ret.getCategories());
} }
} }
private void setDisplayTextForRelations(final AtlasGlossaryTerm ret) throws AtlasBaseException { private void setInfoForRelations(final AtlasGlossaryTerm ret) throws AtlasBaseException {
if (Objects.nonNull(ret.getCategories())) { if (Objects.nonNull(ret.getCategories())) {
setDisplayNameForTermCategories(ret.getCategories()); setDisplayNameForTermCategories(ret.getCategories());
} }
if (Objects.nonNull(ret.getRelatedTerms())) { if (Objects.nonNull(ret.getRelatedTerms())) {
for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : ret.getRelatedTerms().entrySet()) { for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : ret.getRelatedTerms().entrySet()) {
setDisplayNameForTerms(entry.getValue()); setInfoForTerms(entry.getValue());
} }
} }
} }
private void setDisplayTextForRelations(final AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException { private void setInfoForRelations(final AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
if (Objects.nonNull(glossaryCategory.getChildrenCategories())) { if (Objects.nonNull(glossaryCategory.getChildrenCategories())) {
setDisplayNameForRelatedCategories(glossaryCategory.getChildrenCategories()); setInfoForRelatedCategories(glossaryCategory.getChildrenCategories());
} }
if (Objects.nonNull(glossaryCategory.getTerms())) { if (Objects.nonNull(glossaryCategory.getTerms())) {
setDisplayNameForTerms(glossaryCategory.getTerms()); setInfoForTerms(glossaryCategory.getTerms());
}
}
private void processRelations(final AtlasGlossaryTerm newObj, final AtlasGlossaryTerm existing) throws AtlasBaseException {
boolean hasRelatedTerms = newObj.hasTerms();
boolean hasTermAnchor = Objects.nonNull(newObj.getAnchor());
boolean hasCategories = Objects.nonNull(newObj.getCategories());
if (hasTermAnchor) {
processTermAnchor(newObj, existing);
}
if (hasRelatedTerms) {
processRelatedTerms(newObj, existing);
}
if (hasCategories) {
processAssociatedCategories(newObj, existing);
}
}
private void processRelations(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
boolean hasParent = Objects.nonNull(newObj.getParentCategory());
boolean hasChildren = Objects.nonNull(newObj.getChildrenCategories());
boolean hasAnchor = Objects.nonNull(newObj.getAnchor());
boolean hasTerms = Objects.nonNull(newObj.getTerms());
if (hasAnchor) {
processCategoryAnchor(newObj, existing);
}
if (hasParent) {
processParentCategory(newObj, existing);
}
if (hasChildren) {
processCategoryChildren(newObj, existing);
}
if (hasTerms) {
processAssociatedTerms(newObj, existing);
} }
} }
...@@ -798,17 +802,23 @@ public class GlossaryService { ...@@ -798,17 +802,23 @@ public class GlossaryService {
categorizationHeaders.forEach(c -> c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName())); categorizationHeaders.forEach(c -> c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName()));
} }
private void setDisplayNameForRelatedCategories(final Set<AtlasRelatedCategoryHeader> categoryHeaders) throws AtlasBaseException { private void setInfoForRelatedCategories(final Set<AtlasRelatedCategoryHeader> categoryHeaders) throws AtlasBaseException {
List<AtlasGlossaryCategory> categories = categoryHeaders List<AtlasGlossaryCategory> categories = categoryHeaders
.stream() .stream()
.map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid())) .map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
.collect(Collectors.toList()); .collect(Collectors.toList());
Map<String, AtlasGlossaryCategory> categoryMap = new HashMap<>(); Map<String, AtlasGlossaryCategory> categoryMap = new HashMap<>();
dataAccess.load(categories).forEach(c -> categoryMap.put(c.getGuid(), c)); dataAccess.load(categories).forEach(c -> categoryMap.put(c.getGuid(), c));
categoryHeaders.forEach(c -> c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName())); for (AtlasRelatedCategoryHeader c : categoryHeaders) {
AtlasGlossaryCategory category = categoryMap.get(c.getCategoryGuid());
c.setDisplayText(category.getDisplayName());
if (Objects.nonNull(category.getParentCategory())) {
c.setParentCategoryGuid(category.getParentCategory().getCategoryGuid());
}
}
} }
private void setDisplayNameForTerms(final Set<AtlasRelatedTermHeader> termHeaders) throws AtlasBaseException { private void setInfoForTerms(final Set<AtlasRelatedTermHeader> termHeaders) throws AtlasBaseException {
List<AtlasGlossaryTerm> terms = termHeaders List<AtlasGlossaryTerm> terms = termHeaders
.stream() .stream()
.map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid())) .map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid()))
...@@ -819,301 +829,6 @@ public class GlossaryService { ...@@ -819,301 +829,6 @@ public class GlossaryService {
termHeaders.forEach(t -> t.setDisplayText(termMap.get(t.getTermGuid()).getDisplayName())); termHeaders.forEach(t -> t.setDisplayText(termMap.get(t.getTermGuid()).getDisplayName()));
} }
private void processAssociatedCategories(final AtlasGlossaryTerm newObj, final AtlasGlossaryTerm existing) throws AtlasBaseException {
if (newObj.equals(existing)) return;
Set<AtlasTermCategorizationHeader> categories = newObj.getCategories();
if (Objects.nonNull(categories)) {
Set<AtlasTermCategorizationHeader> existingCategories = existing.getCategories();
for (AtlasTermCategorizationHeader category : categories) {
if (Objects.isNull(category.getCategoryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Linked category guid can't be empty");
} else {
if (Objects.nonNull(existingCategories) && existingCategories.contains(category)) {
if (DEBUG_ENABLED) {
LOG.debug("Skipping linked category {}", category.getCategoryGuid());
}
continue;
}
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between term = {} and category = {}", existing.getGuid(), category.getCategoryGuid());
}
createRelationship(defineCategorizedTerm(category, existing.getGuid()));
}
}
}
}
private void processAssociatedTerms(final AtlasGlossaryCategory glossaryCategory, final AtlasGlossaryCategory existing) throws AtlasBaseException {
if (Objects.equals(glossaryCategory.getTerms(), existing.getTerms())) return;
for (AtlasRelatedTermHeader linkedTerm : glossaryCategory.getTerms()) {
if (Objects.isNull(linkedTerm.getTermGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Linked term guid can't be empty");
} else {
// Don't process existing child relation
Set<AtlasRelatedTermHeader> existingTerms = existing.getTerms();
if (Objects.nonNull(existingTerms) && existingTerms.contains(linkedTerm)) {
if (DEBUG_ENABLED) {
LOG.debug("Skipping linked term {}", linkedTerm.getTermGuid());
}
continue;
}
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between category = {} and term = {}", existing.getGuid(), linkedTerm.getTermGuid());
}
// TODO: Accept the relationship attributes as well
createRelationship(defineCategorizedTerm(existing.getGuid(), linkedTerm));
}
}
}
private void processTermAnchor(final AtlasGlossaryTerm glossaryTerm, final AtlasGlossaryTerm saved) throws AtlasBaseException {
if (Objects.isNull(glossaryTerm.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryTerm anchor mandatory attribute");
}
if (Objects.equals(glossaryTerm.getAnchor(), saved.getAnchor())) return;
if (Objects.isNull(glossaryTerm.getAnchor().getGlossaryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Anchor guid can't be empty");
} else {
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between glossary = {} and term = {}", glossaryTerm.getAnchor().getGlossaryGuid(), saved.getGuid());
}
createRelationship(defineTermAnchorRelation(glossaryTerm.getAnchor().getGlossaryGuid(), saved.getGuid()));
}
}
private void processCategoryAnchor(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
if (Objects.isNull(newObj.getAnchor())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryCategory anchor mandatory attribute");
}
// Don't process anchor if no change
if (Objects.equals(newObj.getAnchor(), existing.getAnchor())) return;
if (Objects.isNull(newObj.getAnchor().getGlossaryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category anchor guid can't be empty");
} else {
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between glossary = {} and category = {}", newObj.getAnchor().getGlossaryGuid(), existing.getGuid());
}
createRelationship(defineCategoryAnchorRelation(newObj.getAnchor().getGlossaryGuid(), existing.getGuid()));
}
}
private void processRelatedTerms(final AtlasGlossaryTerm incomingObj, final AtlasGlossaryTerm savedObj) throws AtlasBaseException {
if (incomingObj.hasTerms()) {
for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : incomingObj.getRelatedTerms().entrySet()) {
AtlasGlossaryTerm.Relation relation = entry.getKey();
Set<AtlasRelatedTermHeader> terms = entry.getValue();
if (DEBUG_ENABLED) {
LOG.debug("Creating relation {}", relation);
LOG.debug("Related Term count = {}", terms.size());
}
if (Objects.nonNull(terms)) {
for (AtlasRelatedTermHeader atlasGlossaryTerm : terms) {
createRelationship(defineTermRelation(relation.getRelationName(), savedObj.getGuid(), atlasGlossaryTerm));
}
}
}
}
// TODO: Process other term relations as well
}
private void processCategoryChildren(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
for (AtlasRelatedCategoryHeader childCategory : newObj.getChildrenCategories()) {
if (Objects.isNull(childCategory.getCategoryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Child category guid can't be empty");
} else {
// Don't process existing child relation
Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories();
if (Objects.nonNull(existingChildren) && existingChildren.contains(childCategory)) {
if (DEBUG_ENABLED) {
LOG.debug("Skipping category child {}", childCategory.getCategoryGuid());
}
continue;
}
if (DEBUG_ENABLED) {
LOG.debug("Creating relation between glossary = {} and term = {}", existing.getGuid(), childCategory.getCategoryGuid());
}
// TODO: Accept the relationship attributes as well
createRelationship(defineCategoryHierarchyLink(existing.getGuid(), childCategory));
}
}
}
private void processParentCategory(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
// Don't process unchanged parent
if (Objects.equals(newObj.getParentCategory(), existing.getParentCategory())) return;
if (Objects.isNull(newObj.getParentCategory().getCategoryGuid())) {
throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Parent category guid can't be empty");
} else {
if (DEBUG_ENABLED) {
LOG.debug("Creating category hierarchy b/w parent = {} and child = {}", newObj.getParentCategory().getCategoryGuid(), existing.getGuid());
}
createRelationship(defineCategoryHierarchyLink(newObj.getParentCategory(), newObj.getGuid()));
}
}
private Map<String, List<AtlasGlossaryTerm>> loadTerms(final Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> relatedTerms,
final int offset,
final int limit,
final SortOrder sortOrder) throws AtlasBaseException {
Map<String, List<AtlasGlossaryTerm>> ret = new HashMap<>();
for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : relatedTerms.entrySet()) {
ret.put(entry.getKey().getRelationAttrName(), loadTerms(entry.getValue(), offset, limit, sortOrder));
}
return ret;
}
private List<AtlasGlossaryTerm> loadTerms(final Set<AtlasRelatedTermHeader> terms,
final int offset,
final int limit,
final SortOrder sortOrder) throws AtlasBaseException {
return loadTerms(new ArrayList<>(terms), offset, limit, sortOrder);
}
private List<AtlasGlossaryTerm> loadTerms(final List<AtlasRelatedTermHeader> terms,
final int offset,
final int limit,
final SortOrder sortOrder) throws AtlasBaseException {
Objects.requireNonNull(terms);
List<AtlasGlossaryTerm> ret;
ret = terms.stream().map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid())).collect(Collectors.toList());
Iterable<AtlasGlossaryTerm> loadedTerms = dataAccess.load(ret);
ret.clear();
loadedTerms.forEach(ret::add);
// Sort only when needed
if (sortOrder != null) {
ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
o1.getDisplayName().compareTo(o2.getDisplayName()) :
o2.getDisplayName().compareTo(o1.getDisplayName()));
}
return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
}
private List<AtlasGlossaryCategory> loadCategories(final Set<AtlasRelatedCategoryHeader> categories,
final int offset,
final int limit,
final SortOrder sortOrder) throws AtlasBaseException {
return loadCategories(new ArrayList<>(categories), offset, limit, sortOrder);
}
private List<AtlasGlossaryCategory> loadCategories(final List<AtlasRelatedCategoryHeader> categories,
final int offset,
final int limit,
final SortOrder sortOrder) throws AtlasBaseException {
Objects.requireNonNull(categories);
List<AtlasGlossaryCategory> ret = categories.stream()
.map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
.collect(Collectors.toList());
Iterable<AtlasGlossaryCategory> loadedCategories = dataAccess.load(ret);
ret.clear();
loadedCategories.forEach(ret::add);
// Sort only when needed
if (sortOrder != null) {
ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
o1.getDisplayName().compareTo(o2.getDisplayName()) :
o2.getDisplayName().compareTo(o1.getDisplayName()));
}
return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
}
private AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String termGuid) {
AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
glossaryTerm.setGuid(termGuid);
return glossaryTerm;
}
private AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final String categoryGuid) {
AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
glossaryCategory.setGuid(categoryGuid);
return glossaryCategory;
}
private void createRelationship(AtlasRelationship relationship) throws AtlasBaseException {
try {
relationshipStore.create(relationship);
} catch (AtlasBaseException e) {
if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIP_ALREADY_EXISTS)) {
throw e;
}
}
}
private AtlasRelationship defineTermAnchorRelation(String glossaryGuid, String termGuid) {
return new AtlasRelationship(TERM_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(termGuid));
}
private AtlasRelationship defineCategoryAnchorRelation(String glossaryGuid, String categoryGuid) {
return new AtlasRelationship(CATEGORY_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(categoryGuid));
}
private AtlasRelationship defineCategoryHierarchyLink(String parentCategoryGuid, AtlasRelatedCategoryHeader childCategory) {
AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategoryGuid), new AtlasObjectId(childCategory.getCategoryGuid()));
relationship.setAttribute("description", childCategory.getDescription());
return relationship;
}
private AtlasRelationship defineCategoryHierarchyLink(final AtlasRelatedCategoryHeader parentCategory, final String childGuid) {
AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategory.getCategoryGuid()), new AtlasObjectId(childGuid));
relationship.setAttribute("description", parentCategory.getDescription());
return relationship;
}
private AtlasRelationship defineCategorizedTerm(String categoryGuid, AtlasRelatedTermHeader relatedTermId) {
AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(categoryGuid), new AtlasObjectId(relatedTermId.getTermGuid()));
relationship.setAttribute("expression", relatedTermId.getExpression());
relationship.setAttribute("description", relatedTermId.getDescription());
relationship.setAttribute("steward", relatedTermId.getSteward());
relationship.setAttribute("source", relatedTermId.getSource());
if (Objects.nonNull(relatedTermId.getStatus())) {
relationship.setAttribute("status", relatedTermId.getStatus().name());
}
return relationship;
}
private AtlasRelationship defineCategorizedTerm(AtlasTermCategorizationHeader relatedCategoryId, String termId) {
AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(relatedCategoryId.getCategoryGuid()), new AtlasObjectId(termId));
relationship.setAttribute("description", relatedCategoryId.getDescription());
if (Objects.nonNull(relatedCategoryId.getStatus())) {
relationship.setAttribute("status", relatedCategoryId.getStatus().name());
}
return relationship;
}
private AtlasRelationship defineTermRelation(String relation, String end1TermGuid, AtlasRelatedTermHeader end2RelatedTerm) {
AtlasRelationship relationship = new AtlasRelationship(relation, new AtlasObjectId(end1TermGuid), new AtlasObjectId(end2RelatedTerm.getTermGuid()));
relationship.setAttribute("expression", end2RelatedTerm.getExpression());
relationship.setAttribute("description", end2RelatedTerm.getDescription());
relationship.setAttribute("steward", end2RelatedTerm.getSteward());
relationship.setAttribute("source", end2RelatedTerm.getSource());
if (Objects.nonNull(end2RelatedTerm.getStatus())) {
relationship.setAttribute("status", end2RelatedTerm.getStatus().name());
}
return relationship;
}
private AtlasRelationship defineTermAssignment(String termGuid, AtlasEntityHeader entityHeader) {
return new AtlasRelationship(TERM_ASSIGNMENT, new AtlasObjectId(termGuid), new AtlasObjectId(entityHeader.getGuid()));
}
static class PaginationHelper<T> { static class PaginationHelper<T> {
private int pageStart; private int pageStart;
private int pageEnd; private int pageEnd;
...@@ -1156,4 +871,5 @@ public class GlossaryService { ...@@ -1156,4 +871,5 @@ public class GlossaryService {
return pageStart <= maxSize; return pageStart <= maxSize;
} }
} }
} }
/**
* 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());
}
}
}
}
/**
* 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
}
}
...@@ -113,7 +113,13 @@ public class DataAccess { ...@@ -113,7 +113,13 @@ public class DataAccess {
List<AtlasBaseModelObject> ret = new ArrayList<>(); List<AtlasBaseModelObject> ret = new ArrayList<>();
for (T object : objects) { 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; return (Iterable<T>) ret;
......
...@@ -20,7 +20,6 @@ package org.apache.atlas.repository.ogm.glossary; ...@@ -20,7 +20,6 @@ package org.apache.atlas.repository.ogm.glossary;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.glossary.AtlasGlossaryTerm; import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
import org.apache.atlas.model.instance.AtlasEntity; 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.AtlasRelatedObjectId;
import org.apache.atlas.model.instance.AtlasRelationship; import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
...@@ -92,12 +91,7 @@ public class AtlasGlossaryTermDTO extends AbstractGlossaryDTO<AtlasGlossaryTerm> ...@@ -92,12 +91,7 @@ public class AtlasGlossaryTermDTO extends AbstractGlossaryDTO<AtlasGlossaryTerm>
if (assignedEntity instanceof AtlasRelatedObjectId) { if (assignedEntity instanceof AtlasRelatedObjectId) {
AtlasRelatedObjectId id = (AtlasRelatedObjectId) assignedEntity; AtlasRelatedObjectId id = (AtlasRelatedObjectId) assignedEntity;
if (id.getRelationshipStatus() == AtlasRelationship.Status.ACTIVE) { if (id.getRelationshipStatus() == AtlasRelationship.Status.ACTIVE) {
AtlasEntityHeader entityHeader = new AtlasEntityHeader(id.getTypeName(), id.getGuid(), id.getUniqueAttributes()); ret.addAssignedEntity(id);
if (entityHeader.getAttributes() == null) {
entityHeader.setAttributes(new HashMap<>());
}
entityHeader.getAttributes().put("relationGuid", id.getRelationshipGuid());
ret.addAssignedEntity(entityHeader);
} }
} }
} }
......
/** /**
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
......
...@@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.type.TypeReference; ...@@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TimeBoundary; 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.glossary.relations.AtlasTermAssignmentHeader;
import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasClassification.PropagationState; import org.apache.atlas.model.instance.AtlasClassification.PropagationState;
...@@ -71,30 +72,16 @@ import java.util.Map; ...@@ -71,30 +72,16 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.atlas.glossary.GlossaryUtils.*;
import static org.apache.atlas.model.instance.AtlasClassification.PropagationState.ACTIVE; 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.instance.AtlasClassification.PropagationState.DELETED;
import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*; 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.model.typedef.AtlasRelationshipDef.PropagateTags.ONE_TO_TWO;
import static org.apache.atlas.repository.Constants.*; import static org.apache.atlas.repository.Constants.CLASSIFICATION_ENTITY_GUID;
import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX; import static org.apache.atlas.repository.Constants.CLASSIFICATION_LABEL;
import static org.apache.atlas.repository.graph.GraphHelper.addToPropagatedTraitNames; import static org.apache.atlas.repository.Constants.CLASSIFICATION_VALIDITY_PERIODS_KEY;
import static org.apache.atlas.repository.graph.GraphHelper.getAdjacentEdgesByLabel; import static org.apache.atlas.repository.Constants.TERM_ASSIGNMENT_LABEL;
import static org.apache.atlas.repository.graph.GraphHelper.getAllClassificationEdges; import static org.apache.atlas.repository.graph.GraphHelper.*;
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.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex; 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;
import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH; import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
...@@ -105,7 +92,11 @@ import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelation ...@@ -105,7 +92,11 @@ import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelation
public final class EntityGraphRetriever { public final class EntityGraphRetriever {
private static final Logger LOG = LoggerFactory.getLogger(EntityGraphRetriever.class); 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 NAME = "name";
private final String DISPLAY_NAME = "displayName";
private final String DESCRIPTION = "description"; private final String DESCRIPTION = "description";
private final String OWNER = "owner"; private final String OWNER = "owner";
private final String CREATE_TIME = "createTime"; private final String CREATE_TIME = "createTime";
...@@ -368,7 +359,9 @@ public final class EntityGraphRetriever { ...@@ -368,7 +359,9 @@ public final class EntityGraphRetriever {
ret.setStatus(GraphHelper.getStatus(entityVertex)); ret.setStatus(GraphHelper.getStatus(entityVertex));
ret.setClassificationNames(getAllTraitNames(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); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
...@@ -410,6 +403,7 @@ public final class EntityGraphRetriever { ...@@ -410,6 +403,7 @@ public final class EntityGraphRetriever {
} }
} }
} }
} }
return ret; return ret;
...@@ -503,6 +497,85 @@ public final class EntityGraphRetriever { ...@@ -503,6 +497,85 @@ public final class EntityGraphRetriever {
return ret; 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 { private void mapClassifications(AtlasVertex entityVertex, AtlasEntity entity) throws AtlasBaseException {
List<AtlasEdge> edges = getAllClassificationEdges(entityVertex); List<AtlasEdge> edges = getAllClassificationEdges(entityVertex);
...@@ -881,6 +954,10 @@ public final class EntityGraphRetriever { ...@@ -881,6 +954,10 @@ public final class EntityGraphRetriever {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME)); ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME));
if (ret == null) { if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME));
}
if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME)); ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME));
} }
} }
......
...@@ -28,8 +28,10 @@ import org.apache.atlas.model.glossary.enums.AtlasTermRelationshipStatus; ...@@ -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.AtlasGlossaryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityHeader; 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.model.instance.EntityMutationResponse;
import org.apache.atlas.repository.impexp.ZipFileResourceTestUtils; import org.apache.atlas.repository.impexp.ZipFileResourceTestUtils;
import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.AtlasEntityStore;
...@@ -49,11 +51,14 @@ import javax.inject.Inject; ...@@ -49,11 +51,14 @@ import javax.inject.Inject;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; 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) @Guice(modules = TestModules.TestOnlyModule.class)
public class GlossaryServiceTest { public class GlossaryServiceTest {
...@@ -68,11 +73,21 @@ public class GlossaryServiceTest { ...@@ -68,11 +73,21 @@ public class GlossaryServiceTest {
@Inject @Inject
private AtlasEntityStore entityStore; private AtlasEntityStore entityStore;
private AtlasGlossary bankGlossary; private AtlasGlossary bankGlossary, creditUnionGlossary;
private AtlasGlossaryTerm checkingAccount, savingsAccount, fixedRateMortgage, adjustableRateMortgage; private AtlasGlossaryTerm checkingAccount, savingsAccount, fixedRateMortgage, adjustableRateMortgage;
private AtlasGlossaryCategory customerCategory, accountCategory, mortgageCategory; 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 @BeforeClass
public void setupSampleGlossary() { public void setupSampleGlossary() {
...@@ -93,19 +108,42 @@ public class GlossaryServiceTest { ...@@ -93,19 +108,42 @@ public class GlossaryServiceTest {
bankGlossary.setUsage("N/A"); bankGlossary.setUsage("N/A");
bankGlossary.setLanguage("en-US"); 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 { try {
AtlasGlossary created = glossaryService.createGlossary(bankGlossary); AtlasGlossary created = glossaryService.createGlossary(bankGlossary);
bankGlossary.setGuid(created.getGuid()); bankGlossary.setGuid(created.getGuid());
created = glossaryService.createGlossary(creditUnionGlossary);
creditUnionGlossary.setGuid(created.getGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Glossary creation should've succeeded", e); fail("Glossary creation should've succeeded", e);
} }
}
@Test(groups = "Glossary.CREATE", dependsOnMethods = {"testCreateGlossary"}) // Glossary anchor
public void testCreateGlossaryTerms() {
AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader(); AtlasGlossaryHeader glossaryId = new AtlasGlossaryHeader();
glossaryId.setGlossaryGuid(bankGlossary.getGuid()); 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 = new AtlasGlossaryTerm();
checkingAccount.setQualifiedName("chk_acc@testBankingGlossary"); checkingAccount.setQualifiedName("chk_acc@testBankingGlossary");
checkingAccount.setDisplayName("A checking account"); checkingAccount.setDisplayName("A checking account");
...@@ -146,22 +184,7 @@ public class GlossaryServiceTest { ...@@ -146,22 +184,7 @@ public class GlossaryServiceTest {
adjustableRateMortgage.setUsage("N/A"); adjustableRateMortgage.setUsage("N/A");
adjustableRateMortgage.setAnchor(glossaryId); adjustableRateMortgage.setAnchor(glossaryId);
try { // Create glossary categories
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());
customerCategory = new AtlasGlossaryCategory(); customerCategory = new AtlasGlossaryCategory();
customerCategory.setQualifiedName("customer@testBankingGlossary"); customerCategory.setQualifiedName("customer@testBankingGlossary");
customerCategory.setDisplayName("Customer category"); customerCategory.setDisplayName("Customer category");
...@@ -169,47 +192,93 @@ public class GlossaryServiceTest { ...@@ -169,47 +192,93 @@ public class GlossaryServiceTest {
customerCategory.setLongDescription("Long description"); customerCategory.setLongDescription("Long description");
customerCategory.setAnchor(glossaryId); 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 = new AtlasGlossaryCategory();
mortgageCategory.setQualifiedName("mtg@testBankingGlossary"); mortgageCategory.setQualifiedName("mtg@testBankingGlossary");
mortgageCategory.setDisplayName("Mortgage categorization"); mortgageCategory.setDisplayName("Mortgage categorization");
mortgageCategory.setShortDescription("Short description"); mortgageCategory.setShortDescription("Short description");
mortgageCategory.setLongDescription("Long description"); mortgageCategory.setLongDescription("Long description");
mortgageCategory.setAnchor(glossaryId); 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 { 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()); customerCategory.setGuid(categories.get(0).getGuid());
accountCategory.setGuid(categories.get(1).getGuid()); mortgageCategory.setGuid(categories.get(1).getGuid());
mortgageCategory.setGuid(categories.get(2).getGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Category creation should've succeeded", e); fail("Category creation should've succeeded", e);
} }
} }
@DataProvider @DataProvider
public Object[][] getAllGlossaryDataProvider() { public Object[][] getAllGlossaryDataProvider() {
return new Object[][]{ return new Object[][]{
// limit, offset, sortOrder, expected // limit, offset, sortOrder, expected
{1, 0, SortOrder.ASCENDING, 1}, {1, 0, SortOrder.ASCENDING, 1},
{5, 0, SortOrder.ASCENDING, 1}, {5, 0, SortOrder.ASCENDING, 2},
{10, 0, SortOrder.ASCENDING, 1}, {10, 0, SortOrder.ASCENDING, 2},
{1, 1, SortOrder.ASCENDING, 0}, {1, 1, SortOrder.ASCENDING, 1},
{5, 1, SortOrder.ASCENDING, 0}, {5, 1, SortOrder.ASCENDING, 1},
{10, 1, SortOrder.ASCENDING, 0}, {10, 1, SortOrder.ASCENDING, 1},
{1, 2, SortOrder.ASCENDING, 0}, {1, 2, SortOrder.ASCENDING, 0},
{5, 2, SortOrder.ASCENDING, 0}, {5, 2, SortOrder.ASCENDING, 0},
{10, 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) { public void testGetAllGlossaries(int limit, int offset, SortOrder sortOrder, int expected) {
try { try {
List<AtlasGlossary> glossaries = glossaryService.getGlossaries(limit, offset, sortOrder); List<AtlasGlossary> glossaries = glossaryService.getGlossaries(limit, offset, sortOrder);
...@@ -219,17 +288,6 @@ public class GlossaryServiceTest { ...@@ -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") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
public void testUpdateGlossary() { public void testUpdateGlossary() {
try { try {
...@@ -241,13 +299,12 @@ public class GlossaryServiceTest { ...@@ -241,13 +299,12 @@ public class GlossaryServiceTest {
assertNotNull(updatedGlossary); assertNotNull(updatedGlossary);
assertEquals(updatedGlossary.getGuid(), bankGlossary.getGuid()); assertEquals(updatedGlossary.getGuid(), bankGlossary.getGuid());
assertEquals(updatedGlossary, bankGlossary); assertEquals(updatedGlossary, bankGlossary);
bankGlossary = updatedGlossary;
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Glossary fetch/update should've succeeded", 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() { public void testDeleteGlossary() {
try { try {
glossaryService.deleteGlossary(bankGlossary.getGuid()); glossaryService.deleteGlossary(bankGlossary.getGuid());
...@@ -261,19 +318,6 @@ public class GlossaryServiceTest { ...@@ -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") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
public void testUpdateGlossaryTerm() { public void testUpdateGlossaryTerm() {
List<AtlasGlossaryTerm> glossaryTerms = new ArrayList<>(); List<AtlasGlossaryTerm> glossaryTerms = new ArrayList<>();
...@@ -298,19 +342,6 @@ public class GlossaryServiceTest { ...@@ -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") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
public void testUpdateGlossaryCategory() { public void testUpdateGlossaryCategory() {
List<AtlasGlossaryCategory> glossaryCategories = new ArrayList<>(); List<AtlasGlossaryCategory> glossaryCategories = new ArrayList<>();
...@@ -324,17 +355,91 @@ public class GlossaryServiceTest { ...@@ -324,17 +355,91 @@ public class GlossaryServiceTest {
for (AtlasGlossaryCategory c : glossaryCategories) { for (AtlasGlossaryCategory c : glossaryCategories) {
try { try {
AtlasGlossaryCategory glossaryCategory = glossaryService.getCategory(c.getGuid()); c.setShortDescription("Updated short description");
glossaryCategory.setShortDescription("Updated short description"); c.setLongDescription("Updated long description");
glossaryCategory.setLongDescription("Updated long description");
AtlasGlossaryCategory updatedCategory = glossaryService.updateCategory(glossaryCategory); AtlasGlossaryCategory updatedCategory = glossaryService.updateCategory(c);
assertNotNull(updatedCategory); assertNotNull(updatedCategory);
assertEquals(updatedCategory.getGuid(), c.getGuid()); assertEquals(updatedCategory.getGuid(), c.getGuid());
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Glossary category fetching should've succeeded", 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") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
...@@ -345,24 +450,22 @@ public class GlossaryServiceTest { ...@@ -345,24 +450,22 @@ public class GlossaryServiceTest {
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Fetch of accountCategory should've succeeded", e); fail("Fetch of accountCategory should've succeeded", e);
} }
List<AtlasGlossaryTerm> terms = new ArrayList<>();
for (AtlasGlossaryTerm term : Arrays.asList(checkingAccount, savingsAccount)) { for (AtlasGlossaryTerm term : Arrays.asList(checkingAccount, savingsAccount)) {
try { 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) { } catch (AtlasBaseException e) {
fail("Term fetching should've succeeded", 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 { try {
AtlasGlossaryCategory updated = glossaryService.updateCategory(accountCategory); AtlasGlossaryCategory updated = glossaryService.updateCategory(accountCategory);
assertNotNull(updated.getTerms()); assertNotNull(updated.getTerms());
...@@ -379,26 +482,23 @@ public class GlossaryServiceTest { ...@@ -379,26 +482,23 @@ public class GlossaryServiceTest {
fail("Fetch of accountCategory should've succeeded", e); fail("Fetch of accountCategory should've succeeded", e);
} }
terms.clear();
for (AtlasGlossaryTerm term : Arrays.asList(fixedRateMortgage, adjustableRateMortgage)) { for (AtlasGlossaryTerm term : Arrays.asList(fixedRateMortgage, adjustableRateMortgage)) {
try { 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) { } catch (AtlasBaseException e) {
fail("Term fetching should've succeeded", 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 { try {
AtlasGlossaryCategory updated = glossaryService.updateCategory(mortgageCategory); AtlasGlossaryCategory updated = glossaryService.updateCategory(mortgageCategory);
assertNotNull(updated.getTerms()); assertNotNull(updated.getTerms());
...@@ -439,77 +539,59 @@ public class GlossaryServiceTest { ...@@ -439,77 +539,59 @@ public class GlossaryServiceTest {
assertNull(updateGlossaryCategory.getParentCategory()); assertNull(updateGlossaryCategory.getParentCategory());
assertNotNull(updateGlossaryCategory.getChildrenCategories()); assertNotNull(updateGlossaryCategory.getChildrenCategories());
assertEquals(updateGlossaryCategory.getChildrenCategories().size(), 2); assertEquals(updateGlossaryCategory.getChildrenCategories().size(), 2);
customerCategory = updateGlossaryCategory;
LOG.debug(AtlasJson.toJson(updateGlossaryCategory)); LOG.debug(AtlasJson.toJson(updateGlossaryCategory));
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Sub category addition should've succeeded", 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; for (AtlasGlossaryCategory childCategory : categories) {
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)) {
try { try {
relatedCategories = glossaryService.getRelatedCategories(childCategory.getGuid(), 0, -1, SortOrder.ASCENDING); AtlasGlossaryCategory child = glossaryService.getCategory(childCategory.getGuid());
assertNotNull(relatedCategories.get("parent")); assertNotNull(child);
assertEquals(relatedCategories.get("parent").size(), 1); assertNotNull(child.getParentCategory());
} catch (AtlasBaseException e) { } 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") @Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE")
public void testTermAssignment() { public void testTermAssignmentAndDissociation() {
AtlasEntity assetEntity = new AtlasEntity("Asset"); AtlasEntity assetEntity = new AtlasEntity("Asset");
assetEntity.setAttribute("qualifiedName", "testAsset"); assetEntity.setAttribute("qualifiedName", "testAsset");
assetEntity.setAttribute("name", "testAsset"); assetEntity.setAttribute("name", "testAsset");
try { try {
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(assetEntity), false); EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(assetEntity), false);
testEntityHeader = response.getFirstEntityCreated(); AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated();
assertNotNull(testEntityHeader); relatedObjectId = new AtlasRelatedObjectId();
relatedObjectId.setGuid(firstEntityCreated.getGuid());
relatedObjectId.setTypeName(firstEntityCreated.getTypeName());
assertNotNull(relatedObjectId);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Entity creation should've succeeded", e); fail("Entity creation should've succeeded", e);
} }
try { try {
glossaryService.assignTermToEntities(fixedRateMortgage.getGuid(), Arrays.asList(testEntityHeader)); glossaryService.assignTermToEntities(fixedRateMortgage.getGuid(), Arrays.asList(relatedObjectId));
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Term assignment to asset should've succeeded", e); fail("Term assignment to asset should've succeeded", e);
} }
try { 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); assertNotNull(assignedEntities);
assertEquals(assignedEntities.size(), 1); assertEquals(assignedEntities.size(), 1);
Object relationGuid = assignedEntities.get(0).getAttribute("relationGuid"); String relationshipGuid = assignedEntities.get(0).getRelationshipGuid();
assertNotNull(relationGuid); assertNotNull(relationshipGuid);
testEntityHeader.setAttribute("relationGuid", relationGuid); relatedObjectId.setRelationshipGuid(relationshipGuid);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("Term fetch should've succeeded",e); fail("Term fetch should've succeeded",e);
} }
} // Dissociate term from entities
// FIXME: The term dissociation is not working as intended.
@Test(groups = "Glossary.UPDATE", dependsOnGroups = "Glossary.CREATE", dependsOnMethods = "testTermAssignment")
public void testTermDissociation() {
try { try {
glossaryService.removeTermFromEntities(fixedRateMortgage.getGuid(), Arrays.asList(testEntityHeader)); glossaryService.removeTermFromEntities(fixedRateMortgage.getGuid(), Arrays.asList(relatedObjectId));
AtlasGlossaryTerm term = glossaryService.getTerm(fixedRateMortgage.getGuid()); AtlasGlossaryTerm term = glossaryService.getTerm(fixedRateMortgage.getGuid());
assertNotNull(term); assertNotNull(term);
assertNull(term.getAssignedEntities()); assertNull(term.getAssignedEntities());
...@@ -538,9 +620,9 @@ public class GlossaryServiceTest { ...@@ -538,9 +620,9 @@ public class GlossaryServiceTest {
checkingAccount.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm))); checkingAccount.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm)));
try { try {
AtlasGlossaryTerm updatedTerm = glossaryService.updateTerm(checkingAccount); checkingAccount = glossaryService.updateTerm(checkingAccount);
assertNotNull(updatedTerm.getSeeAlso()); assertNotNull(checkingAccount.getSeeAlso());
assertEquals(updatedTerm.getSeeAlso().size(), 1); assertEquals(checkingAccount.getSeeAlso().size(), 1);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("RelatedTerm association should've succeeded", e); fail("RelatedTerm association should've succeeded", e);
} }
...@@ -557,26 +639,16 @@ public class GlossaryServiceTest { ...@@ -557,26 +639,16 @@ public class GlossaryServiceTest {
adjustableRateMortgage.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm))); adjustableRateMortgage.setSeeAlso(new HashSet<>(Arrays.asList(relatedTerm)));
try { try {
AtlasGlossaryTerm updatedTerm = glossaryService.updateTerm(adjustableRateMortgage); adjustableRateMortgage = glossaryService.updateTerm(adjustableRateMortgage);
assertNotNull(updatedTerm.getSeeAlso()); assertNotNull(adjustableRateMortgage.getSeeAlso());
assertEquals(updatedTerm.getSeeAlso().size(), 1); assertEquals(adjustableRateMortgage.getSeeAlso().size(), 1);
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
fail("RelatedTerm association should've succeeded", e); fail("RelatedTerm association should've succeeded", e);
} }
} }
@DataProvider @Test(dataProvider = "getGlossaryTermsProvider" , groups = "Glossary.GET.postUpdate", dependsOnGroups = "Glossary.UPDATE")
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")
public void testGetGlossaryTerms(int offset, int limit, int expected) { public void testGetGlossaryTerms(int offset, int limit, int expected) {
String guid = bankGlossary.getGuid(); String guid = bankGlossary.getGuid();
SortOrder sortOrder = SortOrder.ASCENDING; SortOrder sortOrder = SortOrder.ASCENDING;
...@@ -600,7 +672,7 @@ public class GlossaryServiceTest { ...@@ -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) { public void testGetGlossaryCategories(int offset, int limit, int expected) {
String guid = bankGlossary.getGuid(); String guid = bankGlossary.getGuid();
SortOrder sortOrder = SortOrder.ASCENDING; SortOrder sortOrder = SortOrder.ASCENDING;
...@@ -626,7 +698,7 @@ public class GlossaryServiceTest { ...@@ -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) { public void testGetCategoryTerms(int offset, int limit, int expected) {
for (AtlasGlossaryCategory c : Arrays.asList(accountCategory, mortgageCategory)) { for (AtlasGlossaryCategory c : Arrays.asList(accountCategory, mortgageCategory)) {
try { try {
......
...@@ -26,7 +26,7 @@ import org.apache.atlas.model.glossary.AtlasGlossaryCategory; ...@@ -26,7 +26,7 @@ import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
import org.apache.atlas.model.glossary.AtlasGlossaryTerm; import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader; import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasRelatedObjectId;
import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.atlas.utils.AtlasPerfTracer;
import org.apache.atlas.web.util.Servlets; import org.apache.atlas.web.util.Servlets;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
...@@ -723,10 +723,10 @@ public class GlossaryREST { ...@@ -723,10 +723,10 @@ public class GlossaryREST {
*/ */
@GET @GET
@Path("/terms/{termGuid}/assignedEntities") @Path("/terms/{termGuid}/assignedEntities")
public List<AtlasEntityHeader> getEntitiesAssignedWithTerm(@PathParam("termGuid") String termGuid, public List<AtlasRelatedObjectId> getEntitiesAssignedWithTerm(@PathParam("termGuid") String termGuid,
@DefaultValue("-1") @QueryParam("limit") String limit, @DefaultValue("-1") @QueryParam("limit") String limit,
@DefaultValue("0") @QueryParam("offset") String offset, @DefaultValue("0") @QueryParam("offset") String offset,
@DefaultValue("ASC") @QueryParam("sort") final String sort) throws AtlasBaseException { @DefaultValue("ASC") @QueryParam("sort") final String sort) throws AtlasBaseException {
Servlets.validateQueryParamLength("termGuid", termGuid); Servlets.validateQueryParamLength("termGuid", termGuid);
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
...@@ -746,7 +746,7 @@ public class GlossaryREST { ...@@ -746,7 +746,7 @@ public class GlossaryREST {
/** /**
* Assign the given term to the provided list of entity headers * Assign the given term to the provided list of entity headers
* @param termGuid Glossary term GUID * @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 * @throws AtlasBaseException
* @HTTP 204 If the term assignment was successful * @HTTP 204 If the term assignment was successful
* @HTTP 400 If ANY of the entity header is invalid * @HTTP 400 If ANY of the entity header is invalid
...@@ -754,7 +754,7 @@ public class GlossaryREST { ...@@ -754,7 +754,7 @@ public class GlossaryREST {
*/ */
@POST @POST
@Path("/terms/{termGuid}/assignedEntities") @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); Servlets.validateQueryParamLength("termGuid", termGuid);
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
...@@ -763,7 +763,7 @@ public class GlossaryREST { ...@@ -763,7 +763,7 @@ public class GlossaryREST {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.assignTermToEntities(" + termGuid + ")"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.assignTermToEntities(" + termGuid + ")");
} }
glossaryService.assignTermToEntities(termGuid, entityHeaders); glossaryService.assignTermToEntities(termGuid, relatedObjectIds);
} finally { } finally {
AtlasPerfTracer.log(perf); AtlasPerfTracer.log(perf);
} }
...@@ -772,7 +772,7 @@ public class GlossaryREST { ...@@ -772,7 +772,7 @@ public class GlossaryREST {
/** /**
* Remove the term assignment for the given list of entity headers * Remove the term assignment for the given list of entity headers
* @param termGuid Glossary term GUID * @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 * @throws AtlasBaseException
* @HTTP 204 If glossary term dissociation was successful * @HTTP 204 If glossary term dissociation was successful
* @HTTP 400 If ANY of the entity header is invalid * @HTTP 400 If ANY of the entity header is invalid
...@@ -780,7 +780,7 @@ public class GlossaryREST { ...@@ -780,7 +780,7 @@ public class GlossaryREST {
*/ */
@DELETE @DELETE
@Path("/terms/{termGuid}/assignedEntities") @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); Servlets.validateQueryParamLength("termGuid", termGuid);
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
...@@ -789,7 +789,7 @@ public class GlossaryREST { ...@@ -789,7 +789,7 @@ public class GlossaryREST {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.removeTermAssignmentFromEntities(" + termGuid + ")"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "GlossaryREST.removeTermAssignmentFromEntities(" + termGuid + ")");
} }
glossaryService.removeTermFromEntities(termGuid, entityHeaders); glossaryService.removeTermFromEntities(termGuid, relatedObjectIds);
} finally { } finally {
AtlasPerfTracer.log(perf); AtlasPerfTracer.log(perf);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment