You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2018/04/10 06:16:47 UTC
[3/5] atlas git commit: ATLAS-2534: Atlas Glossary - REST API
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
new file mode 100644
index 0000000..91abf5e
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/glossary/GlossaryService.java
@@ -0,0 +1,1159 @@
+/**
+ * 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.SortOrder;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.glossary.AtlasGlossary;
+import org.apache.atlas.model.glossary.AtlasGlossaryCategory;
+import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
+import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.AtlasRelationship;
+import org.apache.atlas.repository.ogm.DataAccess;
+import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
+import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
+import org.apache.commons.collections.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+public class GlossaryService {
+ private static final Logger LOG = LoggerFactory.getLogger(GlossaryService.class);
+ private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
+
+ private static final String ATLAS_GLOSSARY_PREFIX = "__AtlasGlossary";
+ // Relation name constants
+ private static final String TERM_ANCHOR = ATLAS_GLOSSARY_PREFIX + "TermAnchor";
+ private static final String CATEGORY_ANCHOR = ATLAS_GLOSSARY_PREFIX + "CategoryAnchor";
+ private static final String CATEGORY_HIERARCHY = ATLAS_GLOSSARY_PREFIX + "CategoryHierarchyLink";
+ private static final String TERM_CATEGORIZATION = ATLAS_GLOSSARY_PREFIX + "TermCategorization";
+ private static final String TERM_ASSIGNMENT = ATLAS_GLOSSARY_PREFIX + "SemanticAssignment";
+
+ private final DataAccess dataAccess;
+ private final AtlasRelationshipStore relationshipStore;
+
+ @Inject
+ public GlossaryService(DataAccess dataAccess, final AtlasRelationshipStore relationshipStore) {
+ this.dataAccess = dataAccess;
+ this.relationshipStore = relationshipStore;
+ }
+
+
+ /**
+ * List all glossaries
+ *
+ * @param limit page size - no paging by default
+ * @param offset offset for pagination
+ * @param sortOrder ASC (default) or DESC
+ * @return List of all glossaries
+ * @throws AtlasBaseException
+ */
+ public List<AtlasGlossary> getGlossaries(int limit, int offset, SortOrder sortOrder) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getGlossaries({}, {}, {})", limit, offset, sortOrder);
+ }
+
+ List<String> glossaryGuids = AtlasGraphUtilsV1.findEntityGUIDsByType(ATLAS_GLOSSARY_PREFIX, sortOrder);
+ PaginationHelper paginationHelper = new PaginationHelper<>(glossaryGuids, offset, limit);
+
+ List<AtlasGlossary> ret;
+ List<String> guidsToLoad = paginationHelper.getPaginatedList();
+ if (CollectionUtils.isNotEmpty(guidsToLoad)) {
+ ret = guidsToLoad.stream().map(GlossaryService::getGlossarySkeleton).collect(Collectors.toList());
+ Iterable<AtlasGlossary> glossaries = dataAccess.load(ret);
+ ret.clear();
+
+ glossaries.forEach(ret::add);
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getGlossaries() : {}", ret);
+ }
+ return ret;
+ }
+
+ /**
+ * Create a glossary
+ *
+ * @param atlasGlossary Glossary specification to be created
+ * @return Glossary definition
+ * @throws AtlasBaseException
+ */
+ public AtlasGlossary createGlossary(AtlasGlossary atlasGlossary) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.createGlossary({})", atlasGlossary);
+ }
+
+ if (Objects.isNull(atlasGlossary)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary definition missing");
+ }
+ if (Objects.isNull(atlasGlossary.getQualifiedName())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary qualifiedName is mandatory");
+
+ }
+ AtlasGlossary saved = dataAccess.save(atlasGlossary);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.createGlossary() : {}", saved);
+ }
+ return saved;
+ }
+
+ /**
+ * Get specific glossary
+ *
+ * @param glossaryGuid unique identifier
+ * @return Glossary corresponding to specified glossaryGuid
+ * @throws AtlasBaseException
+ */
+ public AtlasGlossary getGlossary(String glossaryGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getGlossary({})", glossaryGuid);
+ }
+
+ if (Objects.isNull(glossaryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
+ }
+
+ AtlasGlossary atlasGlossary = getGlossarySkeleton(glossaryGuid);
+ AtlasGlossary ret = dataAccess.load(atlasGlossary);
+
+ setDisplayTextForRelations(ret);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getGlossary() : {}", ret);
+ }
+ return ret;
+ }
+
+ /**
+ * Get specific glossary
+ *
+ * @param glossaryGuid unique identifier
+ * @return Glossary corresponding to specified glossaryGuid
+ * @throws AtlasBaseException
+ */
+ public AtlasGlossary.AtlasGlossaryExtInfo getDetailedGlossary(String glossaryGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getGlossary({})", glossaryGuid);
+ }
+
+ if (Objects.isNull(glossaryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
+ }
+
+ AtlasGlossary atlasGlossary = getGlossarySkeleton(glossaryGuid);
+ AtlasGlossary glossary = dataAccess.load(atlasGlossary);
+
+ AtlasGlossary.AtlasGlossaryExtInfo ret = new AtlasGlossary.AtlasGlossaryExtInfo(glossary);
+
+ // Load all linked terms
+ if (CollectionUtils.isNotEmpty(ret.getTerms())) {
+ List<AtlasGlossaryTerm> termsToLoad = ret.getTerms()
+ .stream()
+ .map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid()))
+ .collect(Collectors.toList());
+ Iterable<AtlasGlossaryTerm> glossaryTerms = dataAccess.load(termsToLoad);
+ glossaryTerms.forEach(ret::addTermInfo);
+ }
+
+ // Load all linked categories
+ if (CollectionUtils.isNotEmpty(ret.getCategories())) {
+ List<AtlasGlossaryCategory> categoriesToLoad = ret.getCategories()
+ .stream()
+ .map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
+ .collect(Collectors.toList());
+ Iterable<AtlasGlossaryCategory> glossaryCategories = dataAccess.load(categoriesToLoad);
+ glossaryCategories.forEach(ret::addCategoryInfo);
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getGlossary() : {}", ret);
+ }
+ return ret;
+ }
+
+ public AtlasGlossary updateGlossary(AtlasGlossary atlasGlossary) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.updateGlossary({})", atlasGlossary);
+ }
+ if (Objects.isNull(atlasGlossary)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Glossary is null/empty");
+ }
+
+ AtlasGlossary ret = dataAccess.load(atlasGlossary);
+
+ if (!ret.equals(atlasGlossary)) {
+ atlasGlossary.setGuid(ret.getGuid());
+ atlasGlossary.setQualifiedName(ret.getQualifiedName());
+
+ ret = dataAccess.save(atlasGlossary);
+ setDisplayTextForRelations(ret);
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.updateGlossary() : {}", ret);
+ }
+ return ret;
+ }
+
+ public void deleteGlossary(String glossaryGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.deleteGlossary({})", glossaryGuid);
+ }
+ if (Objects.isNull(glossaryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
+ }
+
+
+ // FIXME: When deleting all other related entities, the new edge label (r:<Relation>) is failing the delete calls
+ dataAccess.delete(glossaryGuid);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.deleteGlossary()");
+ }
+ }
+
+ /*
+ * GlossaryTerms related operations
+ * */
+ public AtlasGlossaryTerm getTerm(String termGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getTerm({})", termGuid);
+ }
+ if (Objects.isNull(termGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
+ }
+
+
+ AtlasGlossaryTerm atlasGlossary = getAtlasGlossaryTermSkeleton(termGuid);
+ AtlasGlossaryTerm ret = dataAccess.load(atlasGlossary);
+
+ setDisplayTextForRelations(ret);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getTerm() : {}", ret);
+ }
+ return ret;
+ }
+
+ public AtlasGlossaryTerm createTerm(AtlasGlossaryTerm glossaryTerm) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.create({})", glossaryTerm);
+ }
+ if (Objects.isNull(glossaryTerm)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryTerm definition missing");
+ }
+ if (Objects.isNull(glossaryTerm.getQualifiedName())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryTerm qualifiedName is mandatory");
+ }
+
+ AtlasGlossaryTerm saved = dataAccess.save(glossaryTerm);
+
+ // TODO: Create all term relations
+ processTermAnchor(glossaryTerm, saved);
+ processRelatedTerms(glossaryTerm, saved);
+ processAssociatedCategories(glossaryTerm, saved);
+
+ saved = dataAccess.load(glossaryTerm);
+ setDisplayTextForRelations(saved);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.create() : {}", saved);
+ }
+ return saved;
+ }
+
+ public List<AtlasGlossaryTerm> createTerms(List<AtlasGlossaryTerm> glossaryTerm) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.create({})", glossaryTerm);
+ }
+
+ if (Objects.isNull(glossaryTerm)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryTerm(s) is null/empty");
+ }
+
+
+ List<AtlasGlossaryTerm> ret = new ArrayList<>();
+ for (AtlasGlossaryTerm atlasGlossaryTerm : glossaryTerm) {
+ ret.add(createTerm(atlasGlossaryTerm));
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== GlossaryService.createTerms() : {}", ret);
+ }
+
+ return ret;
+ }
+
+ public AtlasGlossaryTerm updateTerm(AtlasGlossaryTerm atlasGlossaryTerm) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.updateTerm({})", atlasGlossaryTerm);
+ }
+ if (Objects.isNull(atlasGlossaryTerm)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "atlasGlossaryTerm is null/empty");
+ }
+
+
+ AtlasGlossaryTerm existing = dataAccess.load(atlasGlossaryTerm);
+ AtlasGlossaryTerm updated = atlasGlossaryTerm;
+ if (!existing.equals(updated)) {
+ try {
+ updated.setGuid(existing.getGuid());
+ updated.setQualifiedName(existing.getQualifiedName());
+
+ atlasGlossaryTerm = dataAccess.save(updated);
+ } catch (AtlasBaseException e) {
+ LOG.debug("Glossary term had no immediate attr updates. Exception: {}", e.getMessage());
+ } finally {
+ // TODO: Manage remaining term relations
+ processRelations(atlasGlossaryTerm, existing);
+ }
+
+ }
+
+ updated = dataAccess.load(atlasGlossaryTerm);
+ setDisplayTextForRelations(updated);
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.updateTerm() : {}", updated);
+ }
+ return updated;
+ }
+
+ public void deleteTerm(String termGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.deleteTerm({})", termGuid);
+ }
+ if (Objects.isNull(termGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
+ }
+
+
+ dataAccess.delete(termGuid);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.deleteTerm()");
+ }
+ }
+
+ public void assignTermToEntities(String termGuid, Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException {
+ AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+
+ if (Objects.nonNull(glossaryTerm)) {
+ Set<AtlasEntityHeader> assignedEntities = glossaryTerm.getAssignedEntities();
+ for (AtlasEntityHeader entityHeader : entityHeaders) {
+ if (CollectionUtils.isNotEmpty(assignedEntities) && assignedEntities.contains(entityHeader)) continue;
+ if (DEBUG_ENABLED) {
+ LOG.debug("Assigning term guid={}, to entity guid = {}", termGuid, entityHeader.getGuid());
+ }
+ createRelationship(defineTermAssignment(termGuid, entityHeader));
+ }
+ }
+ }
+
+ public void removeTermFromEntities(String termGuid, Collection<AtlasEntityHeader> entityHeaders) throws AtlasBaseException {
+ AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+
+ if (Objects.nonNull(glossaryTerm)) {
+ for (AtlasEntityHeader entityHeader : entityHeaders) {
+ if (DEBUG_ENABLED) {
+ LOG.debug("Removing term guid={}, from entity guid = {}", termGuid, entityHeader.getGuid());
+ }
+ Object relationGuid = entityHeader.getAttribute("relationGuid");
+ if (Objects.isNull(relationGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "EntityHeader is missing mandatory attribute relation guid");
+ }
+ relationshipStore.deleteById((String) relationGuid);
+ }
+ }
+ }
+
+ /*
+ * GlossaryCategory related operations
+ * */
+ public AtlasGlossaryCategory getCategory(String categoryGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getCategory({})", categoryGuid);
+ }
+ if (Objects.isNull(categoryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "categoryGuid is null/empty");
+ }
+
+
+ AtlasGlossaryCategory atlasGlossary = getAtlasGlossaryCategorySkeleton(categoryGuid);
+ AtlasGlossaryCategory ret = dataAccess.load(atlasGlossary);
+
+ setDisplayTextForRelations(ret);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getCategory() : {}", ret);
+ }
+ return ret;
+ }
+
+ public AtlasGlossaryCategory createCategory(AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.createCategory({})", glossaryCategory);
+ }
+
+ if (Objects.isNull(glossaryCategory)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory definition missing");
+ }
+ if (Objects.isNull(glossaryCategory.getQualifiedName())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory qualifiedName is mandatory");
+ }
+
+ AtlasGlossaryCategory saved = dataAccess.save(glossaryCategory);
+
+ // Attempt relation creation
+ if (Objects.nonNull(glossaryCategory.getAnchor())) {
+ processCategoryAnchor(glossaryCategory, saved);
+ }
+
+ if (Objects.nonNull(glossaryCategory.getParentCategory())) {
+ processParentCategory(glossaryCategory, saved);
+ }
+
+ if (CollectionUtils.isNotEmpty(glossaryCategory.getChildrenCategories())) {
+ processCategoryChildren(glossaryCategory, saved);
+ }
+
+ saved = dataAccess.load(glossaryCategory);
+
+ setDisplayTextForRelations(glossaryCategory);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.createCategory() : {}", saved);
+ }
+
+ return saved;
+ }
+
+ public List<AtlasGlossaryCategory> createCategories(List<AtlasGlossaryCategory> glossaryCategory) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.createCategories({})", glossaryCategory);
+ }
+ if (Objects.isNull(glossaryCategory)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryCategory is null/empty");
+ }
+
+
+ List<AtlasGlossaryCategory> ret = new ArrayList<>();
+ for (AtlasGlossaryCategory category : glossaryCategory) {
+ ret.add(createCategory(category));
+ }
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.createCategories() : {}", ret);
+ }
+ return ret;
+ }
+
+ public AtlasGlossaryCategory updateCategory(AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.updateCategory({})", glossaryCategory);
+ }
+ if (Objects.isNull(glossaryCategory)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "GlossaryCategory is null/empty");
+ }
+
+ AtlasGlossaryCategory existing = dataAccess.load(glossaryCategory);
+ AtlasGlossaryCategory ret = glossaryCategory;
+
+ if (!existing.equals(glossaryCategory)) {
+ try {
+ glossaryCategory.setGuid(existing.getGuid());
+ glossaryCategory.setQualifiedName(existing.getQualifiedName());
+
+ ret = dataAccess.save(glossaryCategory);
+ } catch (AtlasBaseException e) {
+ LOG.debug("No immediate attribute update. Exception: {}", e.getMessage());
+ } finally {
+ processRelations(glossaryCategory, existing);
+ }
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.updateCategory() : {}", ret);
+ }
+ ret = dataAccess.load(glossaryCategory);
+
+ setDisplayTextForRelations(glossaryCategory);
+
+ return ret;
+ }
+
+ public void deleteCategory(String categoryGuid) throws AtlasBaseException {
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.deleteCategory({})", categoryGuid);
+ }
+ if (Objects.isNull(categoryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category guid is null/empty");
+ }
+
+ dataAccess.delete(categoryGuid);
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.deleteCategory()");
+ }
+
+ }
+
+ public List<AtlasGlossaryTerm> getGlossaryTerms(String glossaryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(glossaryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getGlossaryTerms({}, {}, {}, {})", glossaryGuid, offset, limit, sortOrder);
+ }
+
+ AtlasGlossary glossary = getGlossary(glossaryGuid);
+
+ List<AtlasGlossaryTerm> ret;
+ if (CollectionUtils.isNotEmpty(glossary.getTerms())) {
+ List<AtlasGlossaryTerm> toLoad = glossary.getTerms().stream()
+ .map(t -> getAtlasGlossaryTermSkeleton(t.getTermGuid()))
+ .collect(Collectors.toList());
+ Iterable<AtlasGlossaryTerm> terms = dataAccess.load(toLoad);
+ toLoad.clear();
+ terms.forEach(toLoad::add);
+ if (sortOrder != null) {
+ toLoad.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayName().compareTo(o2.getDisplayName()) :
+ o2.getDisplayName().compareTo(o1.getDisplayName()));
+ }
+ ret = new PaginationHelper<>(toLoad, offset, limit).getPaginatedList();
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getGlossaryTerms() : {}", ret);
+ }
+
+ return ret;
+ }
+
+ public List<AtlasRelatedCategoryHeader> getGlossaryCategories(String glossaryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(glossaryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryGuid is null/empty");
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getGlossaryCategories({}, {}, {}, {})", glossaryGuid, offset, limit, sortOrder);
+ }
+
+ AtlasGlossary glossary = getGlossary(glossaryGuid);
+
+ List<AtlasRelatedCategoryHeader> ret;
+
+ List<AtlasRelatedCategoryHeader> categories = new ArrayList<>(glossary.getCategories());
+ if (CollectionUtils.isNotEmpty(categories)) {
+ if (sortOrder != null) {
+ categories.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayText().compareTo(o2.getDisplayText()) :
+ o2.getDisplayText().compareTo(o1.getDisplayText()));
+ }
+ ret = new PaginationHelper<>(categories, offset, limit).getPaginatedList();
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getGlossaryCategories() : {}", ret);
+ }
+
+ return ret;
+ }
+
+ public List<AtlasRelatedTermHeader> getCategoryTerms(String categoryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(categoryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "categoryGuid is null/empty");
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getCategoryTerms({}, {}, {}, {})", categoryGuid, offset, limit, sortOrder);
+ }
+ AtlasGlossaryCategory glossaryCategory = getCategory(categoryGuid);
+
+ List<AtlasRelatedTermHeader> ret;
+ List<AtlasRelatedTermHeader> terms = new ArrayList<>(glossaryCategory.getTerms());
+ if (CollectionUtils.isNotEmpty(glossaryCategory.getTerms())) {
+ if (sortOrder != null) {
+ terms.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayText().compareTo(o2.getDisplayText()) :
+ o2.getDisplayText().compareTo(o1.getDisplayText()));
+ }
+ ret = new PaginationHelper<>(terms, offset, limit).getPaginatedList();
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getCategoryTerms() : {}", ret);
+ }
+ return ret;
+ }
+
+ public Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> getRelatedTerms(String termGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(termGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getRelatedTerms({}, {}, {}, {})", termGuid, offset, limit, sortOrder);
+ }
+
+ AtlasGlossaryTerm glossaryTerm = getTerm(termGuid);
+ Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> ret;
+ if (glossaryTerm.hasTerms()) {
+ ret = glossaryTerm.getRelatedTerms();
+ } else {
+ ret = Collections.emptyMap();
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getRelatedTerms() : {}", ret);
+ }
+
+ return ret;
+ }
+
+ public Map<String, List<AtlasRelatedCategoryHeader>> getRelatedCategories(String categoryGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(categoryGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "categoryGuid is null/empty");
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("==> GlossaryService.getRelatedCategories({}, {}, {}, {})", categoryGuid, offset, limit, sortOrder);
+ }
+
+ AtlasGlossaryCategory glossaryCategory = getCategory(categoryGuid);
+
+ Map<String, List<AtlasRelatedCategoryHeader>> ret = new HashMap<>();
+ if (glossaryCategory.getParentCategory() != null) {
+ ret.put("parent", new ArrayList<AtlasRelatedCategoryHeader>() {{
+ add(glossaryCategory.getParentCategory());
+ }});
+ }
+ if (CollectionUtils.isNotEmpty(glossaryCategory.getChildrenCategories())) {
+ ret.put("children", new ArrayList<>(glossaryCategory.getChildrenCategories()));
+ }
+
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("<== GlossaryService.getRelatedCategories() : {}", ret);
+ }
+
+ return ret;
+ }
+
+ public List<AtlasEntityHeader> getAssignedEntities(final String termGuid, int offset, int limit, SortOrder sortOrder) throws AtlasBaseException {
+ if (Objects.isNull(termGuid)) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "termGuid is null/empty");
+ }
+
+ AtlasGlossaryTerm glossaryTerm = dataAccess.load(getAtlasGlossaryTermSkeleton(termGuid));
+ Set<AtlasEntityHeader> assignedEntities = glossaryTerm.getAssignedEntities();
+
+ List<AtlasEntityHeader> ret;
+ if (CollectionUtils.isNotEmpty(assignedEntities)) {
+ ret = new ArrayList<>(assignedEntities);
+ if (sortOrder != null) {
+ ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayText().compareTo(o2.getDisplayText()) :
+ o2.getDisplayText().compareTo(o1.getDisplayText()));
+ }
+ ret = new PaginationHelper<>(assignedEntities, offset, limit).getPaginatedList();
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ return ret;
+ }
+
+ private static AtlasGlossary getGlossarySkeleton(String glossaryGuid) {
+ AtlasGlossary glossary = new AtlasGlossary();
+ glossary.setGuid(glossaryGuid);
+ return glossary;
+ }
+
+ private void processAssignedEntities(final AtlasGlossaryTerm newObj, final AtlasGlossaryTerm existing) throws AtlasBaseException {
+ if (newObj.equals(existing)) return;
+
+ if (CollectionUtils.isNotEmpty(newObj.getAssignedEntities())) {
+ for (AtlasEntityHeader entityHeader : newObj.getAssignedEntities()) {
+ createRelationship(defineTermAssignment(existing.getGuid(), entityHeader));
+ }
+ }
+ }
+
+ private void setDisplayTextForRelations(final AtlasGlossary ret) throws AtlasBaseException {
+ if (Objects.nonNull(ret.getTerms())) {
+ setDisplayNameForTerms(ret.getTerms());
+ }
+
+ if (Objects.nonNull(ret.getCategories())) {
+ setDisplayNameForRelatedCategories(ret.getCategories());
+ }
+ }
+
+ private void setDisplayTextForRelations(final AtlasGlossaryTerm ret) throws AtlasBaseException {
+ if (Objects.nonNull(ret.getCategories())) {
+ setDisplayNameForTermCategories(ret.getCategories());
+ }
+ if (Objects.nonNull(ret.getRelatedTerms())) {
+ for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : ret.getRelatedTerms().entrySet()) {
+ setDisplayNameForTerms(entry.getValue());
+ }
+ }
+ }
+
+ private void setDisplayTextForRelations(final AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
+ if (Objects.nonNull(glossaryCategory.getChildrenCategories())) {
+ setDisplayNameForRelatedCategories(glossaryCategory.getChildrenCategories());
+ }
+ if (Objects.nonNull(glossaryCategory.getTerms())) {
+ setDisplayNameForTerms(glossaryCategory.getTerms());
+ }
+ }
+
+ private void processRelations(final AtlasGlossaryTerm newObj, final AtlasGlossaryTerm existing) throws AtlasBaseException {
+ boolean hasRelatedTerms = newObj.hasTerms();
+ boolean hasTermAnchor = Objects.nonNull(newObj.getAnchor());
+ boolean hasCategories = Objects.nonNull(newObj.getCategories());
+
+ if (hasTermAnchor) {
+ processTermAnchor(newObj, existing);
+ }
+ if (hasRelatedTerms) {
+ processRelatedTerms(newObj, existing);
+ }
+ if (hasCategories) {
+ processAssociatedCategories(newObj, existing);
+ }
+ }
+
+ private void processRelations(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
+ boolean hasParent = Objects.nonNull(newObj.getParentCategory());
+ boolean hasChildren = Objects.nonNull(newObj.getChildrenCategories());
+ boolean hasAnchor = Objects.nonNull(newObj.getAnchor());
+ boolean hasTerms = Objects.nonNull(newObj.getTerms());
+
+ if (hasAnchor) {
+ processCategoryAnchor(newObj, existing);
+ }
+ if (hasParent) {
+ processParentCategory(newObj, existing);
+ }
+ if (hasChildren) {
+ processCategoryChildren(newObj, existing);
+ }
+ if (hasTerms) {
+ processAssociatedTerms(newObj, existing);
+ }
+ }
+
+ private void setDisplayNameForTermCategories(final Set<AtlasTermCategorizationHeader> categorizationHeaders) throws AtlasBaseException {
+ List<AtlasGlossaryCategory> categories = categorizationHeaders
+ .stream()
+ .map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
+ .collect(Collectors.toList());
+ Map<String, AtlasGlossaryCategory> categoryMap = new HashMap<>();
+ dataAccess.load(categories).forEach(c -> categoryMap.put(c.getGuid(), c));
+ categorizationHeaders.forEach(c -> c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName()));
+ }
+
+ private void setDisplayNameForRelatedCategories(final Set<AtlasRelatedCategoryHeader> categoryHeaders) throws AtlasBaseException {
+ List<AtlasGlossaryCategory> categories = categoryHeaders
+ .stream()
+ .map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
+ .collect(Collectors.toList());
+ Map<String, AtlasGlossaryCategory> categoryMap = new HashMap<>();
+ dataAccess.load(categories).forEach(c -> categoryMap.put(c.getGuid(), c));
+ categoryHeaders.forEach(c -> c.setDisplayText(categoryMap.get(c.getCategoryGuid()).getDisplayName()));
+ }
+
+ private void setDisplayNameForTerms(final Set<AtlasRelatedTermHeader> termHeaders) throws AtlasBaseException {
+ List<AtlasGlossaryTerm> terms = termHeaders
+ .stream()
+ .map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid()))
+ .collect(Collectors.toList());
+ Map<String, AtlasGlossaryTerm> termMap = new HashMap<>();
+ dataAccess.load(terms).iterator().forEachRemaining(t -> termMap.put(t.getGuid(), t));
+
+ 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(), glossaryTerm.getGuid()));
+ }
+ }
+
+ private void processCategoryAnchor(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
+ if (Objects.isNull(newObj.getAnchor())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "glossaryCategory anchor mandatory attribute");
+ }
+
+ // Don't process anchor if no change
+ if (Objects.equals(newObj.getAnchor(), existing.getAnchor())) return;
+
+ if (Objects.isNull(newObj.getAnchor().getGlossaryGuid())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Category anchor guid can't be empty");
+ } else {
+ if (DEBUG_ENABLED) {
+ LOG.debug("Creating relation between glossary = {} and category = {}", newObj.getAnchor().getGlossaryGuid(), existing.getGuid());
+ }
+ createRelationship(defineCategoryAnchorRelation(newObj.getAnchor().getGlossaryGuid(), existing.getGuid()));
+ }
+ }
+
+ private void processRelatedTerms(final AtlasGlossaryTerm incomingObj, final AtlasGlossaryTerm savedObj) throws AtlasBaseException {
+ if (incomingObj.hasTerms()) {
+ for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : incomingObj.getRelatedTerms().entrySet()) {
+ AtlasGlossaryTerm.Relation relation = entry.getKey();
+ Set<AtlasRelatedTermHeader> terms = entry.getValue();
+ if (DEBUG_ENABLED) {
+ LOG.debug("Creating relation {}", relation);
+ LOG.debug("Related Term count = {}", terms.size());
+ }
+ if (Objects.nonNull(terms)) {
+ for (AtlasRelatedTermHeader atlasGlossaryTerm : terms) {
+ createRelationship(defineTermRelation(relation.getRelationName(), savedObj.getGuid(), atlasGlossaryTerm));
+ }
+ }
+ }
+ }
+ // TODO: Process other term relations as well
+ }
+
+ private void processCategoryChildren(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
+ for (AtlasRelatedCategoryHeader childCategory : newObj.getChildrenCategories()) {
+ if (Objects.isNull(childCategory.getCategoryGuid())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Child category guid can't be empty");
+ } else {
+ // Don't process existing child relation
+ Set<AtlasRelatedCategoryHeader> existingChildren = existing.getChildrenCategories();
+ if (Objects.nonNull(existingChildren) && existingChildren.contains(childCategory)) {
+ if (DEBUG_ENABLED) {
+ LOG.debug("Skipping category child {}", childCategory.getCategoryGuid());
+ }
+ continue;
+ }
+
+ if (DEBUG_ENABLED) {
+ LOG.debug("Creating relation between glossary = {} and term = {}", existing.getGuid(), childCategory.getCategoryGuid());
+ }
+ // TODO: Accept the relationship attributes as well
+ createRelationship(defineCategoryHierarchyLink(existing.getGuid(), childCategory));
+ }
+ }
+ }
+
+ private void processParentCategory(final AtlasGlossaryCategory newObj, final AtlasGlossaryCategory existing) throws AtlasBaseException {
+ // Don't process unchanged parent
+ if (Objects.equals(newObj.getParentCategory(), existing.getParentCategory())) return;
+
+ if (Objects.isNull(newObj.getParentCategory().getCategoryGuid())) {
+ throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Parent category guid can't be empty");
+ } else {
+ if (DEBUG_ENABLED) {
+ LOG.debug("Creating category hierarchy b/w parent = {} and child = {}", newObj.getParentCategory().getCategoryGuid(), existing.getGuid());
+ }
+ createRelationship(defineCategoryHierarchyLink(newObj.getParentCategory(), newObj.getGuid()));
+ }
+ }
+
+ private Map<String, List<AtlasGlossaryTerm>> loadTerms(final Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> relatedTerms,
+ final int offset,
+ final int limit,
+ final SortOrder sortOrder) throws AtlasBaseException {
+ Map<String, List<AtlasGlossaryTerm>> ret = new HashMap<>();
+
+ for (Map.Entry<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> entry : relatedTerms.entrySet()) {
+ ret.put(entry.getKey().getRelationAttrName(), loadTerms(entry.getValue(), offset, limit, sortOrder));
+ }
+
+ return ret;
+ }
+
+ private List<AtlasGlossaryTerm> loadTerms(final Set<AtlasRelatedTermHeader> terms,
+ final int offset,
+ final int limit,
+ final SortOrder sortOrder) throws AtlasBaseException {
+ return loadTerms(new ArrayList<>(terms), offset, limit, sortOrder);
+ }
+
+ private List<AtlasGlossaryTerm> loadTerms(final List<AtlasRelatedTermHeader> terms,
+ final int offset,
+ final int limit,
+ final SortOrder sortOrder) throws AtlasBaseException {
+ Objects.requireNonNull(terms);
+ List<AtlasGlossaryTerm> ret;
+
+ ret = terms.stream().map(id -> getAtlasGlossaryTermSkeleton(id.getTermGuid())).collect(Collectors.toList());
+ Iterable<AtlasGlossaryTerm> loadedTerms = dataAccess.load(ret);
+ ret.clear();
+ loadedTerms.forEach(ret::add);
+ // Sort only when needed
+ if (sortOrder != null) {
+ ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayName().compareTo(o2.getDisplayName()) :
+ o2.getDisplayName().compareTo(o1.getDisplayName()));
+ }
+ return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
+ }
+
+ private List<AtlasGlossaryCategory> loadCategories(final Set<AtlasRelatedCategoryHeader> categories,
+ final int offset,
+ final int limit,
+ final SortOrder sortOrder) throws AtlasBaseException {
+ return loadCategories(new ArrayList<>(categories), offset, limit, sortOrder);
+ }
+
+ private List<AtlasGlossaryCategory> loadCategories(final List<AtlasRelatedCategoryHeader> categories,
+ final int offset,
+ final int limit,
+ final SortOrder sortOrder) throws AtlasBaseException {
+ Objects.requireNonNull(categories);
+ List<AtlasGlossaryCategory> ret = categories.stream()
+ .map(id -> getAtlasGlossaryCategorySkeleton(id.getCategoryGuid()))
+ .collect(Collectors.toList());
+ Iterable<AtlasGlossaryCategory> loadedCategories = dataAccess.load(ret);
+ ret.clear();
+ loadedCategories.forEach(ret::add);
+
+ // Sort only when needed
+ if (sortOrder != null) {
+ ret.sort((o1, o2) -> sortOrder == SortOrder.ASCENDING ?
+ o1.getDisplayName().compareTo(o2.getDisplayName()) :
+ o2.getDisplayName().compareTo(o1.getDisplayName()));
+ }
+
+ return new PaginationHelper<>(ret, offset, limit).getPaginatedList();
+ }
+
+ private AtlasGlossaryTerm getAtlasGlossaryTermSkeleton(final String termGuid) {
+ AtlasGlossaryTerm glossaryTerm = new AtlasGlossaryTerm();
+ glossaryTerm.setGuid(termGuid);
+ return glossaryTerm;
+ }
+
+ private AtlasGlossaryCategory getAtlasGlossaryCategorySkeleton(final String categoryGuid) {
+ AtlasGlossaryCategory glossaryCategory = new AtlasGlossaryCategory();
+ glossaryCategory.setGuid(categoryGuid);
+ return glossaryCategory;
+ }
+
+ private void createRelationship(AtlasRelationship relationship) throws AtlasBaseException {
+ try {
+ relationshipStore.create(relationship);
+ } catch (AtlasBaseException e) {
+ if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIP_ALREADY_EXISTS)) {
+ throw e;
+ }
+ }
+ }
+
+ private AtlasRelationship defineTermAnchorRelation(String glossaryGuid, String termGuid) {
+ return new AtlasRelationship(TERM_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(termGuid));
+ }
+
+ private AtlasRelationship defineCategoryAnchorRelation(String glossaryGuid, String categoryGuid) {
+ return new AtlasRelationship(CATEGORY_ANCHOR, new AtlasObjectId(glossaryGuid), new AtlasObjectId(categoryGuid));
+ }
+
+ private AtlasRelationship defineCategoryHierarchyLink(String parentCategoryGuid, AtlasRelatedCategoryHeader childCategory) {
+ AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategoryGuid), new AtlasObjectId(childCategory.getCategoryGuid()));
+ relationship.setAttribute("description", childCategory.getDescription());
+ return relationship;
+ }
+
+ private AtlasRelationship defineCategoryHierarchyLink(final AtlasRelatedCategoryHeader parentCategory, final String childGuid) {
+ AtlasRelationship relationship = new AtlasRelationship(CATEGORY_HIERARCHY, new AtlasObjectId(parentCategory.getCategoryGuid()), new AtlasObjectId(childGuid));
+ relationship.setAttribute("description", parentCategory.getDescription());
+ return relationship;
+ }
+
+ private AtlasRelationship defineCategorizedTerm(String categoryGuid, AtlasRelatedTermHeader relatedTermId) {
+ AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(categoryGuid), new AtlasObjectId(relatedTermId.getTermGuid()));
+
+ relationship.setAttribute("expression", relatedTermId.getExpression());
+ relationship.setAttribute("description", relatedTermId.getDescription());
+ relationship.setAttribute("steward", relatedTermId.getSteward());
+ relationship.setAttribute("source", relatedTermId.getSource());
+ if (Objects.nonNull(relatedTermId.getStatus())) {
+ relationship.setAttribute("status", relatedTermId.getStatus().name());
+ }
+
+ return relationship;
+ }
+
+ private AtlasRelationship defineCategorizedTerm(AtlasTermCategorizationHeader relatedCategoryId, String termId) {
+ AtlasRelationship relationship = new AtlasRelationship(TERM_CATEGORIZATION, new AtlasObjectId(relatedCategoryId.getCategoryGuid()), new AtlasObjectId(termId));
+
+ relationship.setAttribute("description", relatedCategoryId.getDescription());
+ if (Objects.nonNull(relatedCategoryId.getStatus())) {
+ relationship.setAttribute("status", relatedCategoryId.getStatus().name());
+ }
+
+ return relationship;
+ }
+
+ private AtlasRelationship defineTermRelation(String relation, String end1TermGuid, AtlasRelatedTermHeader end2RelatedTerm) {
+ AtlasRelationship relationship = new AtlasRelationship(relation, new AtlasObjectId(end1TermGuid), new AtlasObjectId(end2RelatedTerm.getTermGuid()));
+
+ relationship.setAttribute("expression", end2RelatedTerm.getExpression());
+ relationship.setAttribute("description", end2RelatedTerm.getDescription());
+ relationship.setAttribute("steward", end2RelatedTerm.getSteward());
+ relationship.setAttribute("source", end2RelatedTerm.getSource());
+ if (Objects.nonNull(end2RelatedTerm.getStatus())) {
+ relationship.setAttribute("status", end2RelatedTerm.getStatus().name());
+ }
+
+ return relationship;
+ }
+
+ private AtlasRelationship defineTermAssignment(String termGuid, AtlasEntityHeader entityHeader) {
+ return new AtlasRelationship(TERM_ASSIGNMENT, new AtlasObjectId(termGuid), new AtlasObjectId(entityHeader.getGuid()));
+ }
+
+ static class PaginationHelper<T> {
+ private int pageStart;
+ private int pageEnd;
+ private int maxSize;
+ private List<T> items;
+
+ PaginationHelper(Collection<T> items, int offset, int limit) {
+ Objects.requireNonNull(items, "items can't be empty/null");
+ this.items = new ArrayList<>(items);
+ this.maxSize = items.size();
+
+ // If limit is negative then limit is effectively the maxSize, else the smaller one out of limit and maxSize
+ int adjustedLimit = limit < 0 ? maxSize : Integer.min(maxSize, limit);
+ // Page starting can only be between zero and adjustedLimit
+ pageStart = Integer.max(0, offset);
+ // Page end can't exceed the maxSize
+ pageEnd = Integer.min(adjustedLimit + pageStart, maxSize);
+ }
+
+ List<T> getPaginatedList() {
+ List<T> ret;
+ if (isValidOffset()) {
+ if (isPagingNeeded()) {
+ ret = items.subList(pageStart, pageEnd);
+ } else {
+ ret = items;
+ }
+ } else {
+ ret = Collections.emptyList();
+ }
+
+ return ret;
+ }
+
+ private boolean isPagingNeeded() {
+ return !(pageStart == 0 && pageEnd == maxSize) && pageStart <= pageEnd;
+ }
+
+ private boolean isValidOffset() {
+ return pageStart <= maxSize;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/AbstractDataTransferObject.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/AbstractDataTransferObject.java b/repository/src/main/java/org/apache/atlas/repository/ogm/AbstractDataTransferObject.java
index f1a8bc9..2afdfe1 100644
--- a/repository/src/main/java/org/apache/atlas/repository/ogm/AbstractDataTransferObject.java
+++ b/repository/src/main/java/org/apache/atlas/repository/ogm/AbstractDataTransferObject.java
@@ -27,14 +27,24 @@ import org.apache.commons.lang3.StringUtils;
public abstract class AbstractDataTransferObject<T extends AtlasBaseModelObject> implements DataTransferObject<T> {
+
+ private static final String DEFAULT_PREFIX = "Atlas";
+
private final AtlasTypeRegistry typeRegistry;
private final Class<T> objectType;
private final String entityTypeName;
+ private final String alternateEntityTypeName;
- protected AbstractDataTransferObject(AtlasTypeRegistry typeRegistry, Class<T> tClass) {
+ protected AbstractDataTransferObject(AtlasTypeRegistry typeRegistry, Class<T> tClass, boolean isInternal) {
this.typeRegistry = typeRegistry;
this.objectType = tClass;
- this.entityTypeName = Constants.INTERNAL_PROPERTY_KEY_PREFIX + objectType.getSimpleName();
+ if (isInternal) {
+ this.entityTypeName = Constants.INTERNAL_PROPERTY_KEY_PREFIX + objectType.getSimpleName();
+ this.alternateEntityTypeName = null;
+ } else {
+ this.entityTypeName = objectType.getSimpleName();
+ this.alternateEntityTypeName = entityTypeName.startsWith(DEFAULT_PREFIX) ? entityTypeName.substring(DEFAULT_PREFIX.length()) : null;
+ }
}
@Override
@@ -44,7 +54,11 @@ public abstract class AbstractDataTransferObject<T extends AtlasBaseModelObject>
@Override
public AtlasEntityType getEntityType() {
- return typeRegistry.getEntityTypeByName(entityTypeName);
+ AtlasEntityType ret = typeRegistry.getEntityTypeByName(entityTypeName);
+ if (ret == null) {
+ ret = typeRegistry.getEntityTypeByName(alternateEntityTypeName);
+ }
+ return ret;
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasSavedSearchDTO.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasSavedSearchDTO.java b/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasSavedSearchDTO.java
deleted file mode 100644
index a1a8f59..0000000
--- a/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasSavedSearchDTO.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * 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.repository.ogm;
-
-import org.apache.atlas.exception.AtlasBaseException;
-import org.apache.atlas.model.discovery.SearchParameters;
-import org.apache.atlas.model.instance.AtlasEntity;
-import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
-import org.apache.atlas.model.profile.AtlasUserSavedSearch;
-import org.apache.atlas.type.AtlasType;
-import org.apache.atlas.type.AtlasTypeRegistry;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class AtlasSavedSearchDTO extends AbstractDataTransferObject<AtlasUserSavedSearch> {
- private static final String PROPERTY_NAME = "name";
- private static final String PROPERTY_OWNER_NAME = "ownerName";
- private static final String PROPERTY_SEARCH_PARAMETERS = "searchParameters";
- private static final String PROPERTY_UNIQUE_NAME = "uniqueName";
- private static final String PROPERTY_SEARCH_TYPE = "searchType";
- private static final String PROPERTY_UI_PARAMETERS = "uiParameters";
-
- public AtlasSavedSearchDTO(AtlasTypeRegistry typeRegistry) {
- super(typeRegistry, AtlasUserSavedSearch.class);
- }
-
- @Override
- public AtlasUserSavedSearch from(AtlasEntity entity) {
- AtlasUserSavedSearch savedSearch = new AtlasUserSavedSearch();
-
- savedSearch.setGuid(entity.getGuid());
- savedSearch.setName((String) entity.getAttribute(PROPERTY_NAME));
- savedSearch.setOwnerName((String) entity.getAttribute(PROPERTY_OWNER_NAME));
- savedSearch.setSearchType(AtlasUserSavedSearch.SavedSearchType.to((String) entity.getAttribute(PROPERTY_SEARCH_TYPE)));
-
- String jsonSearchParams = (String) entity.getAttribute(PROPERTY_SEARCH_PARAMETERS);
-
- if (StringUtils.isNotEmpty(jsonSearchParams)) {
- savedSearch.setSearchParameters(AtlasType.fromJson(jsonSearchParams, SearchParameters.class));
- }
-
- savedSearch.setUiParameters((String) entity.getAttribute(PROPERTY_UI_PARAMETERS));
-
- return savedSearch;
- }
-
- @Override
- public AtlasUserSavedSearch from(AtlasEntityWithExtInfo entityWithExtInfo) {
- return from(entityWithExtInfo.getEntity());
- }
-
- @Override
- public AtlasEntity toEntity(AtlasUserSavedSearch obj) throws AtlasBaseException {
- AtlasEntity entity = getDefaultAtlasEntity(obj);
-
- entity.setAttribute(PROPERTY_NAME, obj.getName());
- entity.setAttribute(PROPERTY_OWNER_NAME, obj.getOwnerName());
- entity.setAttribute(PROPERTY_SEARCH_TYPE, obj.getSearchType());
- entity.setAttribute(PROPERTY_UNIQUE_NAME, getUniqueValue(obj));
-
- if (obj.getSearchParameters() != null) {
- entity.setAttribute(PROPERTY_SEARCH_PARAMETERS, AtlasType.toJson(obj.getSearchParameters()));
- }
-
- entity.setAttribute(PROPERTY_UI_PARAMETERS, obj.getUiParameters());
-
- return entity;
- }
-
- @Override
- public AtlasEntityWithExtInfo toEntityWithExtInfo(AtlasUserSavedSearch obj) throws AtlasBaseException {
- return new AtlasEntityWithExtInfo(toEntity(obj));
- }
-
- @Override
- public Map<String, Object> getUniqueAttributes(AtlasUserSavedSearch obj) {
- Map<String, Object> ret = new HashMap<>();
-
- ret.put(PROPERTY_UNIQUE_NAME, getUniqueValue(obj));
-
- return ret;
- }
-
- private String getUniqueValue(AtlasUserSavedSearch obj) {
- return String.format("%s:%s", obj.getOwnerName(), obj.getName()) ;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasUserProfileDTO.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasUserProfileDTO.java b/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasUserProfileDTO.java
deleted file mode 100644
index bcf2b9d..0000000
--- a/repository/src/main/java/org/apache/atlas/repository/ogm/AtlasUserProfileDTO.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * 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.repository.ogm;
-
-import org.apache.atlas.exception.AtlasBaseException;
-import org.apache.atlas.model.instance.AtlasEntity;
-import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
-import org.apache.atlas.model.instance.AtlasObjectId;
-import org.apache.atlas.model.profile.AtlasUserProfile;
-import org.apache.atlas.model.profile.AtlasUserSavedSearch;
-import org.apache.atlas.type.AtlasTypeRegistry;
-
-import java.util.*;
-
-public class AtlasUserProfileDTO extends AbstractDataTransferObject<AtlasUserProfile> {
- private final String PROPERTY_USER_NAME = "name";
- private final String PROPERTY_FULL_NAME = "fullName";
- private final String PROPERTY_SAVED_SEARCHES = "savedSearches";
-
- private final AtlasSavedSearchDTO savedSearchDTO;
-
- public AtlasUserProfileDTO(AtlasTypeRegistry typeRegistry, AtlasSavedSearchDTO savedSearchDTO) {
- super(typeRegistry, AtlasUserProfile.class);
-
- this.savedSearchDTO = savedSearchDTO;
- }
-
- public AtlasUserProfile from(AtlasEntity entity) {
- AtlasUserProfile profile = new AtlasUserProfile();
-
- profile.setGuid(entity.getGuid());
- profile.setName((String) entity.getAttribute(PROPERTY_USER_NAME));
- profile.setFullName((String) entity.getAttribute(PROPERTY_FULL_NAME));
-
- return profile;
- }
-
- public AtlasUserProfile from(AtlasEntityWithExtInfo entityWithExtInfo) {
- AtlasUserProfile userProfile = from(entityWithExtInfo.getEntity());
-
- Object savedSearches = entityWithExtInfo.getEntity().getAttribute(PROPERTY_SAVED_SEARCHES);
-
- if (savedSearches instanceof Collection) {
- for (Object o : (Collection) savedSearches) {
- if (o instanceof AtlasObjectId) {
- AtlasObjectId ssObjId = (AtlasObjectId) o;
- AtlasEntity ssEntity = entityWithExtInfo.getReferredEntity(ssObjId.getGuid());
-
- if (ssEntity != null && ssEntity.getStatus() == AtlasEntity.Status.ACTIVE) {
- AtlasUserSavedSearch savedSearch = savedSearchDTO.from(ssEntity);
- userProfile.getSavedSearches().add(savedSearch);
- }
- }
- }
- }
-
- return userProfile;
- }
-
- @Override
- public AtlasEntity toEntity(AtlasUserProfile obj) throws AtlasBaseException {
- AtlasEntity entity = getDefaultAtlasEntity(obj);
-
- entity.setAttribute(PROPERTY_USER_NAME, obj.getName());
- entity.setAttribute(PROPERTY_FULL_NAME, obj.getFullName());
-
- return entity;
- }
-
- @Override
- public AtlasEntityWithExtInfo toEntityWithExtInfo(AtlasUserProfile obj) throws AtlasBaseException {
- AtlasEntity entity = toEntity(obj);
- AtlasEntityWithExtInfo entityWithExtInfo = new AtlasEntityWithExtInfo(entity);
-
- List<AtlasObjectId> objectIds = new ArrayList<>();
-
- for (AtlasUserSavedSearch ss : obj.getSavedSearches()) {
- AtlasEntity ssEntity = savedSearchDTO.toEntity(ss);
-
- entityWithExtInfo.addReferredEntity(ssEntity);
-
- objectIds.add(new AtlasObjectId(ssEntity.getGuid(), savedSearchDTO.getEntityType().getTypeName(), savedSearchDTO.getUniqueAttributes(ss)));
- }
-
- if (objectIds.size() > 0) {
- entity.setAttribute(PROPERTY_SAVED_SEARCHES, objectIds);
- }
-
- return entityWithExtInfo;
- }
-
- @Override
- public Map<String, Object> getUniqueAttributes(AtlasUserProfile obj) {
- Map<String, Object> ret = new HashMap<>();
-
- ret.put(PROPERTY_USER_NAME, obj.getName());
-
- return ret;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java b/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java
index 818960d..43f4a60 100644
--- a/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java
+++ b/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java
@@ -17,29 +17,30 @@
*/
package org.apache.atlas.repository.ogm;
-import org.apache.atlas.type.AtlasTypeRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
-import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
@Component
public class DTORegistry {
- private final Map<Type, DataTransferObject> typeDTOMap = new HashMap<>();
+ private static final Logger LOG = LoggerFactory.getLogger(DTORegistry.class);
+ private final Map<Class, DataTransferObject> typeDTOMap = new HashMap<>();
@Inject
- public DTORegistry(AtlasTypeRegistry typeRegistry) {
- AtlasSavedSearchDTO savedSearchDTO = new AtlasSavedSearchDTO(typeRegistry);
- AtlasUserProfileDTO userProfileDTO = new AtlasUserProfileDTO(typeRegistry, savedSearchDTO);
-
- registerDTO(savedSearchDTO);
- registerDTO(userProfileDTO);
+ public DTORegistry(Set<DataTransferObject> availableDTOs) {
+ for (DataTransferObject availableDTO : availableDTOs) {
+ LOG.info("Registering DTO: {}", availableDTO.getClass().getSimpleName());
+ registerDTO(availableDTO);
+ }
}
- public <T extends DataTransferObject> DataTransferObject get(Type t) {
+ public <T extends DataTransferObject> DataTransferObject get(Class t) {
return typeDTOMap.get(t);
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java
index c99d2f8..e00c3e9 100644
--- a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java
+++ b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java
@@ -20,18 +20,29 @@ package org.apache.atlas.repository.ogm;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.AtlasBaseModelObject;
+import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
+import org.apache.atlas.utils.AtlasPerfTracer;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
@Component
public class DataAccess {
+ private static final Logger LOG = LoggerFactory.getLogger(DataAccess.class);
+ private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("repository.DataAccess");
+
private final AtlasEntityStore entityStore;
private final DTORegistry dtoRegistry;
@@ -42,49 +53,186 @@ public class DataAccess {
}
public <T extends AtlasBaseModelObject> T save(T obj) throws AtlasBaseException {
- DataTransferObject<T> dto = (DataTransferObject<T>)dtoRegistry.get(obj.getClass());
+ Objects.requireNonNull(obj, "Can't save a null object");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.save()");
+ }
+
+ DataTransferObject<T> dto = (DataTransferObject<T>) dtoRegistry.get(obj.getClass());
+
+ AtlasEntityWithExtInfo entityWithExtInfo = dto.toEntityWithExtInfo(obj);
+ EntityMutationResponse entityMutationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entityWithExtInfo), false);
+
+ if (noEntityMutation(entityMutationResponse)) {
+ throw new AtlasBaseException(AtlasErrorCode.DATA_ACCESS_SAVE_FAILED, obj.toString());
+ }
- AtlasEntityWithExtInfo entityWithExtInfo = dto.toEntityWithExtInfo(obj);
- EntityMutationResponse entityMutationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entityWithExtInfo), false);
+ // Since mutation context has guid information, attempt to set the same.
+ if (entityMutationResponse.getFirstEntityCreated() != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Object created");
+ }
+ obj.setGuid(entityMutationResponse.getFirstEntityCreated().getGuid());
+ } else if (entityMutationResponse.getFirstEntityUpdated() != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Object updated");
+ }
+ obj.setGuid(entityMutationResponse.getFirstEntityUpdated().getGuid());
+ }
- if (hasError(entityMutationResponse)) {
- throw new AtlasBaseException(AtlasErrorCode.DATA_ACCESS_SAVE_FAILED, obj.toString());
+ return this.load(obj);
+
+ } finally {
+ AtlasPerfTracer.log(perf);
}
- return this.load(obj);
+ }
+
+ public <T extends AtlasBaseModelObject> Iterable<T> save(Iterable<T> obj) throws AtlasBaseException {
+ Objects.requireNonNull(obj, "Can't save a null object");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.multiSave()");
+ }
+
+ List<T> ret = new ArrayList<>();
+ for (T o : obj) {
+ ret.add(save(o));
+ }
+ return ret;
+
+ } finally {
+ AtlasPerfTracer.log(perf);
+ }
+ }
+
+ public <T extends AtlasBaseModelObject> Iterable<T> load(final Iterable<T> objects) throws AtlasBaseException {
+ Objects.requireNonNull(objects, "Objects to load");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.multiLoad()");
+ }
+
+ List<AtlasBaseModelObject> ret = new ArrayList<>();
+
+ for (T object : objects) {
+ ret.add(load(object));
+ }
+
+ return (Iterable<T>) ret;
+
+ } finally {
+ AtlasPerfTracer.log(perf);
+ }
}
public <T extends AtlasBaseModelObject> T load(T obj) throws AtlasBaseException {
- DataTransferObject<T> dto = (DataTransferObject<T>)dtoRegistry.get(obj.getClass());
+ return load(obj, false);
+ }
+
+ public <T extends AtlasBaseModelObject> T load(T obj, boolean loadDeleted) throws AtlasBaseException {
+ Objects.requireNonNull(obj, "Can't load a null object");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.load()");
+ }
+
+ DataTransferObject<T> dto = (DataTransferObject<T>) dtoRegistry.get(obj.getClass());
+
+ AtlasEntityWithExtInfo entityWithExtInfo;
- AtlasEntityWithExtInfo entityWithExtInfo;
+ if (StringUtils.isNotEmpty(obj.getGuid())) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Load using GUID");
+ }
+ entityWithExtInfo = entityStore.getById(obj.getGuid());
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Load using unique attributes");
+ }
+ entityWithExtInfo = entityStore.getByUniqueAttributes(dto.getEntityType(), dto.getUniqueAttributes(obj));
+ }
- if (StringUtils.isNotEmpty(obj.getGuid())) {
- entityWithExtInfo = entityStore.getById(obj.getGuid());
- } else {
- entityWithExtInfo = entityStore.getByUniqueAttributes(dto.getEntityType(), dto.getUniqueAttributes(obj));
+ if (!loadDeleted && entityWithExtInfo.getEntity().getStatus() == AtlasEntity.Status.DELETED) {
+ throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_DELETED, obj.getGuid());
+ }
+
+ return dto.from(entityWithExtInfo);
+
+ } finally {
+ AtlasPerfTracer.log(perf);
}
- return dto.from(entityWithExtInfo);
}
+ public void delete(String guid) throws AtlasBaseException {
+ Objects.requireNonNull(guid, "guid");
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.delete()");
+ }
+
+ entityStore.deleteById(guid);
+
+ } finally {
+ AtlasPerfTracer.log(perf);
+ }
+ }
+
+ public void delete(List<String> guids) throws AtlasBaseException {
+ Objects.requireNonNull(guids, "guids");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.multiDelete()");
+ }
+
+ entityStore.deleteByIds(guids);
- public void deleteUsingGuid(String guid) throws AtlasBaseException {
- entityStore.deleteById(guid);
+ } finally {
+ AtlasPerfTracer.log(perf);
+ }
}
public <T extends AtlasBaseModelObject> void delete(T obj) throws AtlasBaseException {
- T object = load(obj);
+ Objects.requireNonNull(obj, "Can't delete a null object");
+
+ AtlasPerfTracer perf = null;
+
+ try {
+ if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+ perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "DataAccess.delete()");
+ }
+
+ T object = load(obj);
+
+ if (object != null) {
+ delete(object.getGuid());
+ }
- if (object != null) {
- deleteUsingGuid(object.getGuid());
+ } finally {
+ AtlasPerfTracer.log(perf);
}
}
- private boolean hasError(EntityMutationResponse er) {
- return (er == null ||
- !((er.getCreatedEntities() != null && er.getCreatedEntities().size() > 0)
- || (er.getUpdatedEntities() != null && er.getUpdatedEntities().size() > 0)
- )
- );
+ // Helper functions
+ private boolean noEntityMutation(EntityMutationResponse er) {
+ return er == null || (CollectionUtils.isEmpty(er.getCreatedEntities()) && CollectionUtils.isEmpty(er.getUpdatedEntities()));
}
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/75415862/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AbstractGlossaryDTO.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AbstractGlossaryDTO.java b/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AbstractGlossaryDTO.java
new file mode 100644
index 0000000..722a463
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/ogm/glossary/AbstractGlossaryDTO.java
@@ -0,0 +1,163 @@
+/**
+ * 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.repository.ogm.glossary;
+
+import org.apache.atlas.model.AtlasBaseModelObject;
+import org.apache.atlas.model.glossary.enums.AtlasTermRelationshipStatus;
+import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedCategoryHeader;
+import org.apache.atlas.model.glossary.relations.AtlasRelatedTermHeader;
+import org.apache.atlas.model.glossary.relations.AtlasTermCategorizationHeader;
+import org.apache.atlas.model.instance.AtlasRelatedObjectId;
+import org.apache.atlas.model.instance.AtlasRelationship;
+import org.apache.atlas.model.instance.AtlasStruct;
+import org.apache.atlas.repository.ogm.AbstractDataTransferObject;
+import org.apache.atlas.type.AtlasTypeRegistry;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class AbstractGlossaryDTO<T extends AtlasBaseModelObject> extends AbstractDataTransferObject<T> {
+ protected AbstractGlossaryDTO(final AtlasTypeRegistry typeRegistry, final Class<T> tClass, final boolean isInternal) {
+ super(typeRegistry, tClass, isInternal);
+ }
+
+ protected AtlasRelatedTermHeader constructRelatedTermId(AtlasRelatedObjectId relatedObjectId) {
+ AtlasRelatedTermHeader ret = new AtlasRelatedTermHeader();
+
+ ret.setTermGuid(relatedObjectId.getGuid());
+ ret.setRelationGuid(relatedObjectId.getRelationshipGuid());
+
+ AtlasStruct relationshipAttributes = relatedObjectId.getRelationshipAttributes();
+ if (relationshipAttributes != null) {
+ ret.setDescription((String) relationshipAttributes.getAttribute("description"));
+ ret.setExpression((String) relationshipAttributes.getAttribute("expression"));
+ ret.setSource((String) relationshipAttributes.getAttribute("source"));
+ ret.setSteward((String) relationshipAttributes.getAttribute("steward"));
+ Object status = relationshipAttributes.getAttribute("status");
+ if (status instanceof String) {
+ ret.setStatus(AtlasTermRelationshipStatus.valueOf((String) status));
+ } else if (status instanceof AtlasTermRelationshipStatus) {
+ ret.setStatus((AtlasTermRelationshipStatus) status);
+ }
+ }
+
+ return ret;
+ }
+
+ protected AtlasRelatedObjectId termIdToRelatedObjectId(AtlasRelatedTermHeader relatedTermId) {
+ AtlasRelatedObjectId ret = new AtlasRelatedObjectId();
+
+ ret.setGuid(relatedTermId.getTermGuid());
+ ret.setRelationshipGuid(relatedTermId.getRelationGuid());
+
+ AtlasStruct relationshipAttributes = new AtlasStruct();
+ relationshipAttributes.setAttribute("description", relatedTermId.getDescription());
+ relationshipAttributes.setAttribute("expression", relatedTermId.getExpression());
+ relationshipAttributes.setAttribute("source", relatedTermId.getSource());
+ relationshipAttributes.setAttribute("steward", relatedTermId.getSteward());
+ relationshipAttributes.setAttribute("status", relatedTermId.getStatus().name());
+
+ ret.setRelationshipAttributes(relationshipAttributes);
+
+ return ret;
+ }
+
+ protected AtlasRelatedCategoryHeader constructRelatedCategoryId(AtlasRelatedObjectId relatedObjectId) {
+ AtlasRelatedCategoryHeader ret = new AtlasRelatedCategoryHeader();
+
+ ret.setCategoryGuid(relatedObjectId.getGuid());
+ ret.setRelationGuid(relatedObjectId.getRelationshipGuid());
+
+ AtlasStruct relationshipAttributes = relatedObjectId.getRelationshipAttributes();
+ if (relationshipAttributes != null) {
+ ret.setDescription((String) relationshipAttributes.getAttribute("description"));
+ }
+
+ return ret;
+ }
+
+ protected AtlasRelatedObjectId relatedCategoryIdToRelatedObjectId(AtlasRelatedCategoryHeader relatedCategoryId) {
+ AtlasRelatedObjectId ret = new AtlasRelatedObjectId();
+
+ ret.setGuid(relatedCategoryId.getCategoryGuid());
+ ret.setRelationshipGuid(relatedCategoryId.getRelationGuid());
+
+ AtlasStruct relationshipAttributes = new AtlasStruct();
+ relationshipAttributes.setAttribute("description", relatedCategoryId.getDescription());
+ ret.setRelationshipAttributes(relationshipAttributes);
+
+ return ret;
+ }
+
+ protected AtlasGlossaryHeader constructGlossaryId(AtlasRelatedObjectId relatedObjectId) {
+ AtlasGlossaryHeader ret = new AtlasGlossaryHeader();
+
+ ret.setGlossaryGuid(relatedObjectId.getGuid());
+ ret.setRelationGuid(relatedObjectId.getRelationshipGuid());
+
+ return ret;
+ }
+
+ protected AtlasRelatedObjectId glossaryIdToRelatedObjectId(AtlasGlossaryHeader glossaryId) {
+ AtlasRelatedObjectId ret = new AtlasRelatedObjectId();
+
+ ret.setGuid(glossaryId.getGlossaryGuid());
+ ret.setRelationshipGuid(glossaryId.getRelationGuid());
+
+ return ret;
+ }
+
+ protected AtlasTermCategorizationHeader constructTermCategorizationId(final AtlasRelatedObjectId category) {
+ AtlasTermCategorizationHeader ret = new AtlasTermCategorizationHeader();
+
+ ret.setCategoryGuid(category.getGuid());
+ ret.setRelationGuid(category.getRelationshipGuid());
+
+ AtlasStruct relationshipAttributes = category.getRelationshipAttributes();
+ if (relationshipAttributes != null) {
+ ret.setDescription((String) relationshipAttributes.getAttribute("description"));
+ Object status = relationshipAttributes.getAttribute("status");
+ if (status instanceof AtlasTermRelationshipStatus) {
+ ret.setStatus((AtlasTermRelationshipStatus) status);
+ } else if (status instanceof String) {
+ ret.setStatus(AtlasTermRelationshipStatus.valueOf((String) status));
+ }
+ }
+
+ return ret;
+ }
+
+ protected Set<AtlasRelatedTermHeader> toRelatedTermIdsSet(Object relatedObjectIds) {
+ Set<AtlasRelatedTermHeader> ret = null;
+
+ if (relatedObjectIds instanceof Collection) {
+ ret = new HashSet<>();
+ for (Object t : (Collection) relatedObjectIds) {
+ if (t instanceof AtlasRelatedObjectId) {
+ if (((AtlasRelatedObjectId) t).getRelationshipStatus() == AtlasRelationship.Status.ACTIVE) {
+ ret.add(constructRelatedTermId((AtlasRelatedObjectId) t));
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+}