diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java index ad94363bf32..48eb8e93ab8 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/Entity.java @@ -179,7 +179,7 @@ public final class Entity { public static EntityReference getOwner(@NonNull EntityReference reference) throws IOException { EntityRepository repository = getEntityRepository(reference.getType()); - return repository.getOwner(reference.getId(), reference.getType()); + return repository.getOwner(reference); } public static void withHref(UriInfo uriInfo, List list) { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/AirflowPipelineRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/AirflowPipelineRepository.java index 73bf56e99cd..0e48d62c2dc 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/AirflowPipelineRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/AirflowPipelineRepository.java @@ -18,7 +18,6 @@ import static org.openmetadata.catalog.Entity.FIELD_OWNER; import java.io.IOException; import java.net.URI; import java.util.UUID; -import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.operations.pipelines.AirflowPipeline; import org.openmetadata.catalog.resources.operations.AirflowPipelineResource; @@ -50,11 +49,6 @@ public class AirflowPipelineRepository extends EntityRepository : null; } - @Transaction - public EntityReference getOwnerReference(AirflowPipeline airflowPipeline) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), airflowPipeline.getOwner()); - } - @Override public AirflowPipeline setFields(AirflowPipeline airflowPipeline, Fields fields) throws IOException { airflowPipeline.setService(getService(airflowPipeline)); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardRepository.java index 3c4d28db7e2..560eb5097a2 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardRepository.java @@ -22,7 +22,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.entity.data.Dashboard; import org.openmetadata.catalog.entity.services.DashboardService; @@ -63,11 +62,6 @@ public class DashboardRepository extends EntityRepository { return new DashboardEntityInterface(entity); } - @Transaction - public EntityReference getOwnerReference(Dashboard dashboard) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), dashboard.getOwner()); - } - @Override public Dashboard setFields(Dashboard dashboard, Fields fields) throws IOException { dashboard.setDisplayName(dashboard.getDisplayName()); @@ -124,7 +118,7 @@ public class DashboardRepository extends EntityRepository { public void prepare(Dashboard dashboard) throws IOException { populateService(dashboard); dashboard.setFullyQualifiedName(getFQN(dashboard)); - EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), dashboard.getOwner()); // Validate owner + populateOwner(dashboard.getOwner()); // Validate owner dashboard.setTags(addDerivedTags(dashboard.getTags())); dashboard.setCharts(getCharts(dashboard.getCharts())); } @@ -156,7 +150,7 @@ public class DashboardRepository extends EntityRepository { } } // Add owner relationship - setOwner(dashboard.getId(), Entity.DASHBOARD, dashboard.getOwner()); + addOwnerRelationship(dashboard.getId(), Entity.DASHBOARD, dashboard.getOwner()); // Add tag to dashboard relationship applyTags(dashboard); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DatabaseRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DatabaseRepository.java index 2be507b1b60..cf7630391d6 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DatabaseRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DatabaseRepository.java @@ -13,15 +13,6 @@ package org.openmetadata.catalog.jdbi3; -import static javax.ws.rs.core.Response.Status.CREATED; -import static org.openmetadata.catalog.Entity.FIELD_OWNER; -import static org.openmetadata.catalog.type.Include.ALL; - -import java.io.IOException; -import java.net.URI; -import java.util.List; -import java.util.UUID; -import javax.ws.rs.core.Response.Status; import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.entity.data.Database; @@ -35,7 +26,16 @@ import org.openmetadata.catalog.type.Relationship; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil.Fields; -import org.openmetadata.catalog.util.JsonUtils; + +import javax.ws.rs.core.Response.Status; +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.UUID; + +import static javax.ws.rs.core.Response.Status.CREATED; +import static org.openmetadata.catalog.Entity.FIELD_OWNER; +import static org.openmetadata.catalog.type.Include.ALL; public class DatabaseRepository extends EntityRepository { private static final String DATABASE_UPDATE_FIELDS = "owner"; @@ -67,9 +67,7 @@ public class DatabaseRepository extends EntityRepository { public void prepare(Database database) throws IOException { populateService(database); database.setFullyQualifiedName(getFQN(database)); - database.setOwner( - EntityUtil.populateOwner( - daoCollection.userDAO(), daoCollection.teamDAO(), database.getOwner())); // Validate owner + populateOwner(database.getOwner()); // Validate owner } @Override @@ -81,11 +79,7 @@ public class DatabaseRepository extends EntityRepository { // Don't store owner, database, href and tags as JSON. Build it on the fly based on relationships database.withOwner(null).withService(null).withHref(null); - if (update) { - daoCollection.databaseDAO().update(database.getId(), JsonUtils.pojoToJson(database)); - } else { - daoCollection.databaseDAO().insert(database); - } + store(database.getId(), database, update); // Restore the relationships database.withOwner(owner).withService(service); @@ -95,7 +89,7 @@ public class DatabaseRepository extends EntityRepository { public void storeRelationships(Database database) { EntityReference service = database.getService(); addRelationship(service.getId(), database.getId(), service.getType(), Entity.DATABASE, Relationship.CONTAINS); - setOwner(database.getId(), Entity.DATABASE, database.getOwner()); + addOwnerRelationship(database.getId(), Entity.DATABASE, database.getOwner()); } private List getTables(Database database) throws IOException { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java index 2dc2d5f8605..1f3a21a225d 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java @@ -13,31 +13,7 @@ package org.openmetadata.catalog.jdbi3; -import static org.openmetadata.catalog.Entity.FIELD_DESCRIPTION; -import static org.openmetadata.catalog.Entity.FIELD_OWNER; -import static org.openmetadata.catalog.Entity.getEntityFields; -import static org.openmetadata.catalog.type.Include.ALL; -import static org.openmetadata.catalog.type.Include.DELETED; -import static org.openmetadata.catalog.util.EntityUtil.compareTagLabel; -import static org.openmetadata.catalog.util.EntityUtil.entityReferenceMatch; -import static org.openmetadata.catalog.util.EntityUtil.nextMajorVersion; -import static org.openmetadata.catalog.util.EntityUtil.nextVersion; -import static org.openmetadata.catalog.util.EntityUtil.objectMatch; -import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; - import com.fasterxml.jackson.core.JsonProcessingException; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.function.BiPredicate; -import java.util.regex.Pattern; -import javax.json.JsonPatch; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriInfo; import lombok.extern.slf4j.Slf4j; import org.apache.maven.shared.utils.io.IOUtil; import org.jdbi.v3.sqlobject.transaction.Transaction; @@ -73,6 +49,31 @@ import org.openmetadata.catalog.util.RestUtil.PutResponse; import org.openmetadata.catalog.util.ResultList; import org.openmetadata.common.utils.CommonUtil; +import javax.json.JsonPatch; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.function.BiPredicate; +import java.util.regex.Pattern; + +import static org.openmetadata.catalog.Entity.FIELD_DESCRIPTION; +import static org.openmetadata.catalog.Entity.FIELD_OWNER; +import static org.openmetadata.catalog.Entity.getEntityFields; +import static org.openmetadata.catalog.type.Include.ALL; +import static org.openmetadata.catalog.type.Include.DELETED; +import static org.openmetadata.catalog.util.EntityUtil.compareTagLabel; +import static org.openmetadata.catalog.util.EntityUtil.entityReferenceMatch; +import static org.openmetadata.catalog.util.EntityUtil.nextMajorVersion; +import static org.openmetadata.catalog.util.EntityUtil.nextVersion; +import static org.openmetadata.catalog.util.EntityUtil.objectMatch; +import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; + /** * This is the base class used by Entity Resources to perform READ and WRITE operations to the backend database to * Create, Retrieve, Update, and Delete entities. @@ -557,34 +558,6 @@ public abstract class EntityRepository { } } - public EntityReference getOriginalOwner(T entity) throws IOException { - if (!supportsOwner) { - return null; - } - // Try to find the owner if entity exists - try { - String fqn = getFullyQualifiedName(entity); - entity = getByName(null, fqn, getFields(FIELD_OWNER)); - return getEntityInterface(entity).getOwner(); - } catch (EntityNotFoundException e) { - // If entity is not found, we can return null for owner and ignore this exception - } - return null; - } - - protected EntityReference getOwner(T entity) throws IOException { - EntityInterface entityInterface = getEntityInterface(entity); - return getOwner(entityInterface.getId(), entityType); - } - - protected void setOwner(T entity, EntityReference owner) { - if (supportsOwner) { - EntityInterface entityInterface = getEntityInterface(entity); - setOwner(entityInterface.getId(), entityType, owner); - entityInterface.setOwner(owner); - } - } - /** Validate given list of tags and add derived tags to it */ public final List addDerivedTags(List tagLabels) throws IOException { if (tagLabels == null || tagLabels.isEmpty()) { @@ -676,11 +649,16 @@ public abstract class EntityRepository { } protected List getFollowers(T entity) throws IOException { + if (!supportsFollower || entity == null) { + return null; + } EntityInterface entityInterface = getEntityInterface(entity); - return !supportsFollower || entity == null - ? null - : EntityUtil.getFollowers( - entityInterface, entityType, daoCollection.relationshipDAO(), daoCollection.userDAO()); + List followers = findFrom(entityInterface.getId(), entityType, Relationship.FOLLOWS); + for (EntityReference follower : followers) { + User user = daoCollection.userDAO().findEntityById(follower.getId(), ALL); + follower.withName(user.getName()).withDeleted(user.getDeleted()); + } + return followers; } public T withHref(UriInfo uriInfo, T entity) { @@ -732,14 +710,6 @@ public abstract class EntityRepository { return daoCollection.relationshipDAO().insert(from, to, fromEntity, toEntity, relationship.ordinal()); } - public void setOwner(UUID ownedEntityId, String ownedEntityType, EntityReference owner) { - // Add relationship owner --- owns ---> ownedEntity - if (owner != null) { - LOG.info("Adding owner {}:{} for entity {}:{}", owner.getType(), owner.getId(), ownedEntityType, ownedEntityId); - addRelationship(owner.getId(), ownedEntityId, owner.getType(), ownedEntityType, Relationship.OWNS); - } - } - public List findBoth(UUID entity1, String entityType1, Relationship relationship, String entity2) { // Find bidirectional relationship List ids = new ArrayList<>(); @@ -779,15 +749,6 @@ public abstract class EntityRepository { } } - public EntityReference getOwner(UUID id, String entityType) throws IOException { - if (!supportsOwner) { - return null; - } - List refs = findFrom(id, entityType, Relationship.OWNS); - ensureSingleRelationship(entityType, id, refs, "owners", false); - return refs.isEmpty() ? null : Entity.getEntityReferenceById(refs.get(0).getType(), refs.get(0).getId(), ALL); - } - public List findTo(UUID fromId, String fromEntityType, Relationship relationship, String toEntityType) { return daoCollection .relationshipDAO() @@ -823,6 +784,77 @@ public abstract class EntityRepository { } } + public EntityReference getOwner(T entity) throws IOException { + if (!supportsOwner) { + return null; + } + EntityInterface entityInterface = getEntityInterface(entity); + List refs = findFrom(entityInterface.getId(), entityType, Relationship.OWNS); + ensureSingleRelationship(entityType, entityInterface.getId(), refs, "owners", false); + return refs.isEmpty() ? null : getOwner(refs.get(0)); + } + + public EntityReference getOwner(EntityReference ref) throws IOException { + return Entity.getEntityReferenceById(ref.getType(), ref.getId(), ALL); + } + + public EntityReference getOriginalOwner(T entity) throws IOException { + if (!supportsOwner) { + return null; + } + // Try to find the owner if entity exists + try { + String fqn = getFullyQualifiedName(entity); + entity = getByName(null, fqn, getFields(FIELD_OWNER)); + return getEntityInterface(entity).getOwner(); + } catch (EntityNotFoundException e) { + // If entity is not found, we can return null for owner and ignore this exception + } + return null; + } + + public EntityReference populateOwner(EntityReference owner) throws IOException { + if (owner == null) { + return null; + } + EntityReference ref = Entity.getEntityReferenceById(owner.getType(), owner.getId(), ALL); + return owner.withName(ref.getName()).withDisplayName(ref.getDisplayName()).withDeleted(ref.getDeleted()); + } + + protected void setOwner(T entity, EntityReference owner) { + if (supportsOwner) { + EntityInterface entityInterface = getEntityInterface(entity); + addOwnerRelationship(entityInterface.getId(), entityType, owner); + entityInterface.setOwner(owner); + } + } + + public void addOwnerRelationship(UUID ownedEntityId, String ownedEntityType, EntityReference owner) { + // Add relationship owner --- owns ---> ownedEntity + if (owner != null) { + LOG.info("Adding owner {}:{} for entity {}:{}", owner.getType(), owner.getId(), ownedEntityType, ownedEntityId); + addRelationship(owner.getId(), ownedEntityId, owner.getType(), ownedEntityType, Relationship.OWNS); + } + } + + /** Remove owner relationship for a given entity */ + private void removeOwnerRelationship(EntityReference owner, String ownedEntityId, String ownedEntityType) { + if (owner != null && owner.getId() != null) { + LOG.info("Removing owner {}:{} for entity {}", owner.getType(), owner.getId(), ownedEntityId); + daoCollection + .relationshipDAO() + .delete( + owner.getId().toString(), owner.getType(), ownedEntityId, ownedEntityType, Relationship.OWNS.ordinal()); + } + } + + public void updateOwnerRelationship( + EntityReference originalOwner, EntityReference newOwner, UUID ownedEntityId, String ownedEntityType) { + // TODO inefficient use replace instead of delete and add and check for orig and new owners being the same + removeOwnerRelationship(originalOwner, ownedEntityId.toString(), ownedEntityType); + addOwnerRelationship(ownedEntityId, ownedEntityType, newOwner); + } + public final Fields getFields(String fields) { return new Fields(allowedFields, fields); } @@ -938,8 +970,7 @@ public abstract class EntityRepository { if (operation.isPatch() || updatedOwner != null) { // Update owner for all PATCH operations. For PUT operations, ownership can't be removed if (recordChange(FIELD_OWNER, origOwner, updatedOwner, true, entityReferenceMatch)) { - EntityUtil.updateOwner( - daoCollection.relationshipDAO(), origOwner, updatedOwner, original.getId(), entityType); + updateOwnerRelationship(origOwner, updatedOwner, original.getId(), entityType); } } } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryRepository.java index c71292cd1f0..f53843a8bba 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryRepository.java @@ -35,7 +35,6 @@ import org.openmetadata.catalog.type.TagLabel.Source; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil.Fields; -import org.openmetadata.catalog.util.JsonUtils; public class GlossaryRepository extends EntityRepository { private static final String UPDATE_FIELDS = "owner,tags,reviewers"; @@ -77,11 +76,7 @@ public class GlossaryRepository extends EntityRepository { // Don't store owner, href and tags as JSON. Build it on the fly based on relationships glossary.withOwner(null).withHref(null).withTags(null); - if (update) { - daoCollection.glossaryDAO().update(glossary.getId(), JsonUtils.pojoToJson(glossary)); - } else { - daoCollection.glossaryDAO().insert(glossary); - } + store(glossary.getId(), glossary, update); // Restore the relationships glossary.withOwner(owner).withTags(tags).withReviewers(reviewers); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryTermRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryTermRepository.java index 60e653b4e97..4d62fd671db 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryTermRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/GlossaryTermRepository.java @@ -41,7 +41,6 @@ import org.openmetadata.catalog.type.TagLabel.Source; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil.Fields; -import org.openmetadata.catalog.util.JsonUtils; @Slf4j public class GlossaryTermRepository extends EntityRepository { @@ -139,11 +138,7 @@ public class GlossaryTermRepository extends EntityRepository { .withHref(null) .withTags(null); - if (update) { - daoCollection.glossaryTermDAO().update(entity.getId(), JsonUtils.pojoToJson(entity)); - } else { - daoCollection.glossaryTermDAO().insert(entity); - } + store(entity.getId(), entity, update); // Restore the relationships entity diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/LocationRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/LocationRepository.java index fa4bbf825e6..7319581a8f5 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/LocationRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/LocationRepository.java @@ -157,11 +157,6 @@ public class LocationRepository extends EntityRepository { : null; } - @Transaction - public EntityReference getOwnerReference(Location location) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), location.getOwner()); - } - private StorageService getService(UUID serviceId, String entityType) throws IOException { if (entityType.equalsIgnoreCase(Entity.STORAGE_SERVICE)) { return daoCollection.storageServiceDAO().findEntityById(serviceId); @@ -177,7 +172,7 @@ public class LocationRepository extends EntityRepository { new StorageServiceRepository.StorageServiceEntityInterface(storageService).getEntityReference()); location.setServiceType(storageService.getServiceType()); location.setFullyQualifiedName(getFQN(location)); - EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), location.getOwner()); // Validate owner + populateOwner(location.getOwner()); // Validate owner location.setTags(addDerivedTags(location.getTags())); } @@ -200,7 +195,7 @@ public class LocationRepository extends EntityRepository { @Override public void storeRelationships(Location location) { // Add location owner relationship - setOwner(location.getId(), Entity.LOCATION, location.getOwner()); + addOwnerRelationship(location.getId(), Entity.LOCATION, location.getOwner()); EntityReference service = location.getService(); addRelationship(service.getId(), location.getId(), service.getType(), Entity.LOCATION, Relationship.CONTAINS); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MetricsRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MetricsRepository.java index 5278bd1befe..e25041aba68 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MetricsRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MetricsRepository.java @@ -69,7 +69,7 @@ public class MetricsRepository extends EntityRepository { @Override public void prepare(Metrics metrics) throws IOException { metrics.setFullyQualifiedName(getFQN(metrics)); - EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), metrics.getOwner()); // Validate owner + populateOwner(metrics.getOwner()); // Validate owner metrics.setService(getService(metrics.getService())); metrics.setTags(addDerivedTags(metrics.getTags())); } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MlModelRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MlModelRepository.java index f6ed6f81af5..e514f4dd74d 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MlModelRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MlModelRepository.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import lombok.extern.slf4j.Slf4j; -import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.entity.data.MlModel; import org.openmetadata.catalog.resources.mlmodels.MlModelResource; @@ -62,11 +61,6 @@ public class MlModelRepository extends EntityRepository { return model.getName(); } - @Transaction - public EntityReference getOwnerReference(MlModel mlModel) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), mlModel.getOwner()); - } - @Override public MlModel setFields(MlModel mlModel, Fields fields) throws IOException { mlModel.setOwner(fields.contains(FIELD_OWNER) ? getOwner(mlModel) : null); @@ -141,7 +135,7 @@ public class MlModelRepository extends EntityRepository { } // Check if owner is valid and set the relationship - mlModel.setOwner(EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), mlModel.getOwner())); + populateOwner(mlModel.getOwner()); // Check that the dashboard exists if (mlModel.getDashboard() != null) { @@ -169,7 +163,7 @@ public class MlModelRepository extends EntityRepository { @Override public void storeRelationships(MlModel mlModel) { - setOwner(mlModel.getId(), Entity.MLMODEL, mlModel.getOwner()); + addOwnerRelationship(mlModel.getId(), Entity.MLMODEL, mlModel.getOwner()); setDashboard(mlModel, mlModel.getDashboard()); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineRepository.java index cfcb56bf31f..aa7d778dbbd 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineRepository.java @@ -67,11 +67,6 @@ public class PipelineRepository extends EntityRepository { : null; } - @Transaction - public EntityReference getOwnerReference(Pipeline pipeline) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), pipeline.getOwner()); - } - @Override public Pipeline setFields(Pipeline pipeline, Fields fields) throws IOException { pipeline.setDisplayName(pipeline.getDisplayName()); @@ -160,7 +155,7 @@ public class PipelineRepository extends EntityRepository { public void prepare(Pipeline pipeline) throws IOException { populateService(pipeline); pipeline.setFullyQualifiedName(getFQN(pipeline)); - EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), pipeline.getOwner()); // Validate owner + populateOwner(pipeline.getOwner()); // Validate owner pipeline.setTags(addDerivedTags(pipeline.getTags())); } @@ -186,7 +181,7 @@ public class PipelineRepository extends EntityRepository { addRelationship(service.getId(), pipeline.getId(), service.getType(), Entity.PIPELINE, Relationship.CONTAINS); // Add owner relationship - setOwner(pipeline.getId(), Entity.PIPELINE, pipeline.getOwner()); + addOwnerRelationship(pipeline.getId(), Entity.PIPELINE, pipeline.getOwner()); // Add tag to pipeline relationship applyTags(pipeline); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java index a86a8472b52..e5f5cda90fa 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java @@ -66,11 +66,6 @@ public class PolicyRepository extends EntityRepository { return policy.getName(); } - @Transaction - public EntityReference getOwnerReference(Policy policy) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), policy.getOwner()); - } - /** Find the location to which this policy applies to. * */ @Transaction private EntityReference getLocationForPolicy(Policy policy) throws IOException { @@ -113,7 +108,7 @@ public class PolicyRepository extends EntityRepository { policy.setFullyQualifiedName(getFQN(policy)); policy.setLocation(getLocationReference(policy)); // Check if owner is valid and set the relationship - policy.setOwner(EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), policy.getOwner())); + populateOwner(policy.getOwner()); } @Override diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java index d10562e371c..ec7c65d682a 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java @@ -588,7 +588,7 @@ public class TableRepository extends EntityRepository { addRelationship(table.getDatabase().getId(), table.getId(), DATABASE, TABLE, Relationship.CONTAINS); // Add table owner relationship - setOwner(table.getId(), TABLE, table.getOwner()); + addOwnerRelationship(table.getId(), TABLE, table.getOwner()); // Add tag to table relationship applyTags(table); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java index 3870c97f86f..7c30662a300 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java @@ -78,7 +78,7 @@ public class TeamRepository extends EntityRepository { @Override public void prepare(Team team) throws IOException { // Check if owner is valid and set the relationship - EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), team.getOwner()); // Validate owner + populateOwner(team.getOwner()); // Validate owner validateUsers(team.getUsers()); validateRoles(team.getDefaultRoles()); } @@ -102,7 +102,7 @@ public class TeamRepository extends EntityRepository { @Override public void storeRelationships(Team team) { // Add team owner relationship - setOwner(team.getId(), TEAM, team.getOwner()); + addOwnerRelationship(team.getId(), TEAM, team.getOwner()); for (EntityReference user : listOrEmpty(team.getUsers())) { addRelationship(team.getId(), user.getId(), TEAM, Entity.USER, Relationship.HAS); } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TopicRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TopicRepository.java index f5aac24d384..272569fe4bd 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TopicRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TopicRepository.java @@ -13,15 +13,7 @@ package org.openmetadata.catalog.jdbi3; -import static org.openmetadata.catalog.Entity.FIELD_OWNER; - import com.fasterxml.jackson.core.JsonProcessingException; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.entity.data.Topic; import org.openmetadata.catalog.entity.services.MessagingService; @@ -37,6 +29,14 @@ import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil.Fields; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.openmetadata.catalog.Entity.FIELD_OWNER; + public class TopicRepository extends EntityRepository { private static final String TOPIC_UPDATE_FIELDS = "owner,tags"; private static final String TOPIC_PATCH_FIELDS = "owner,tags"; @@ -58,11 +58,6 @@ public class TopicRepository extends EntityRepository { TOPIC_UPDATE_FIELDS); } - @Transaction - public EntityReference getOwnerReference(Topic topic) throws IOException { - return EntityUtil.populateOwner(daoCollection.userDAO(), daoCollection.teamDAO(), topic.getOwner()); - } - @Override public void prepare(Topic topic) throws IOException { MessagingService messagingService = Entity.getEntity(topic.getService(), Fields.EMPTY_FIELDS, Include.ALL); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java index 59a11121f16..3c35573603c 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java @@ -13,8 +13,37 @@ package org.openmetadata.catalog.util; -import static org.openmetadata.catalog.type.Include.ALL; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.Period; +import org.joda.time.format.ISOPeriodFormat; +import org.openmetadata.catalog.Entity; +import org.openmetadata.catalog.api.data.TermReference; +import org.openmetadata.catalog.entity.data.GlossaryTerm; +import org.openmetadata.catalog.entity.data.Table; +import org.openmetadata.catalog.exception.CatalogExceptionMessage; +import org.openmetadata.catalog.exception.EntityNotFoundException; +import org.openmetadata.catalog.jdbi3.CollectionDAO.EntityVersionPair; +import org.openmetadata.catalog.jdbi3.CollectionDAO.UsageDAO; +import org.openmetadata.catalog.resources.feeds.MessageParser.EntityLink; +import org.openmetadata.catalog.type.ChangeEvent; +import org.openmetadata.catalog.type.Column; +import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.EventFilter; +import org.openmetadata.catalog.type.EventType; +import org.openmetadata.catalog.type.FailureDetails; +import org.openmetadata.catalog.type.FieldChange; +import org.openmetadata.catalog.type.MlFeature; +import org.openmetadata.catalog.type.MlHyperParameter; +import org.openmetadata.catalog.type.Schedule; +import org.openmetadata.catalog.type.TableConstraint; +import org.openmetadata.catalog.type.TagLabel; +import org.openmetadata.catalog.type.Task; +import org.openmetadata.catalog.type.UsageDetails; +import org.openmetadata.catalog.type.UsageStats; +import javax.ws.rs.WebApplicationException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -27,42 +56,8 @@ import java.util.UUID; import java.util.function.BiPredicate; import java.util.regex.Pattern; import java.util.stream.Collectors; -import javax.ws.rs.WebApplicationException; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.joda.time.Period; -import org.joda.time.format.ISOPeriodFormat; -import org.openmetadata.catalog.Entity; -import org.openmetadata.catalog.api.data.TermReference; -import org.openmetadata.catalog.entity.data.GlossaryTerm; -import org.openmetadata.catalog.entity.data.Table; -import org.openmetadata.catalog.entity.teams.Team; -import org.openmetadata.catalog.entity.teams.User; -import org.openmetadata.catalog.exception.CatalogExceptionMessage; -import org.openmetadata.catalog.exception.EntityNotFoundException; -import org.openmetadata.catalog.jdbi3.CollectionDAO.EntityRelationshipDAO; -import org.openmetadata.catalog.jdbi3.CollectionDAO.EntityVersionPair; -import org.openmetadata.catalog.jdbi3.CollectionDAO.TeamDAO; -import org.openmetadata.catalog.jdbi3.CollectionDAO.UsageDAO; -import org.openmetadata.catalog.jdbi3.CollectionDAO.UserDAO; -import org.openmetadata.catalog.resources.feeds.MessageParser.EntityLink; -import org.openmetadata.catalog.type.ChangeEvent; -import org.openmetadata.catalog.type.Column; -import org.openmetadata.catalog.type.EntityReference; -import org.openmetadata.catalog.type.EventFilter; -import org.openmetadata.catalog.type.EventType; -import org.openmetadata.catalog.type.FailureDetails; -import org.openmetadata.catalog.type.FieldChange; -import org.openmetadata.catalog.type.MlFeature; -import org.openmetadata.catalog.type.MlHyperParameter; -import org.openmetadata.catalog.type.Relationship; -import org.openmetadata.catalog.type.Schedule; -import org.openmetadata.catalog.type.TableConstraint; -import org.openmetadata.catalog.type.TagLabel; -import org.openmetadata.catalog.type.Task; -import org.openmetadata.catalog.type.UsageDetails; -import org.openmetadata.catalog.type.UsageStats; + +import static org.openmetadata.catalog.type.Include.ALL; @Slf4j public final class EntityUtil { @@ -167,66 +162,6 @@ public final class EntityUtil { return entity; } - public static void validateUser(UserDAO userDAO, UUID userId) { - if (!userDAO.exists(userId)) { - throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityNotFound(Entity.USER, userId)); - } - } - - public static EntityReference populateOwner(UserDAO userDAO, TeamDAO teamDAO, EntityReference owner) - throws IOException { - if (owner == null) { - return null; - } - UUID id = owner.getId(); - if (owner.getType().equalsIgnoreCase("user")) { - User ownerInstance = userDAO.findEntityById(id); - owner.setName(ownerInstance.getName()); - owner.setDisplayName(ownerInstance.getDisplayName()); - if (Optional.ofNullable(ownerInstance.getDeleted()).orElse(false)) { - throw new IllegalArgumentException(CatalogExceptionMessage.deactivatedUser(id)); - } - } else if (owner.getType().equalsIgnoreCase("team")) { - Team ownerInstance = teamDAO.findEntityById(id); - owner.setDescription(ownerInstance.getDescription()); - owner.setName(ownerInstance.getName()); - owner.setDisplayName(ownerInstance.getDisplayName()); - } else { - throw new IllegalArgumentException(String.format("Invalid ownerType %s", owner.getType())); - } - return owner; - } - - public static void setOwner( - EntityRelationshipDAO dao, UUID ownedEntityId, String ownedEntityType, EntityReference owner) { - // Add relationship owner --- owns ---> ownedEntity - if (owner != null) { - LOG.info("Adding owner {}:{} for entity {}:{}", owner.getType(), owner.getId(), ownedEntityType, ownedEntityId); - dao.insert(owner.getId(), ownedEntityId, owner.getType(), ownedEntityType, Relationship.OWNS.ordinal()); - } - } - - /** Unassign owner relationship for a given entity */ - public static void unassignOwner( - EntityRelationshipDAO dao, EntityReference owner, String ownedEntityId, String ownedEntityType) { - if (owner != null && owner.getId() != null) { - LOG.info("Removing owner {}:{} for entity {}", owner.getType(), owner.getId(), ownedEntityId); - dao.delete( - owner.getId().toString(), owner.getType(), ownedEntityId, ownedEntityType, Relationship.OWNS.ordinal()); - } - } - - public static void updateOwner( - EntityRelationshipDAO dao, - EntityReference originalOwner, - EntityReference newOwner, - UUID ownedEntityId, - String ownedEntityType) { - // TODO inefficient use replace instead of delete and add and check for orig and new owners being the same - unassignOwner(dao, originalOwner, ownedEntityId.toString(), ownedEntityType); - setOwner(dao, ownedEntityId, ownedEntityType, newOwner); - } - public static List populateEntityReferences(List list) throws IOException { if (list != null) { for (EntityReference ref : list) { @@ -284,41 +219,6 @@ public final class EntityUtil { } } - public static boolean addFollower( - EntityRelationshipDAO dao, - UserDAO userDAO, - UUID followedEntityId, - String followedEntityType, - UUID followerId, - String followerEntity) - throws IOException { - User user = userDAO.findEntityById(followerId); - if (Optional.ofNullable(user.getDeleted()).orElse(false)) { - throw new IllegalArgumentException(CatalogExceptionMessage.deactivatedUser(followerId)); - } - return dao.insert(followerId, followedEntityId, followerEntity, followedEntityType, Relationship.FOLLOWS.ordinal()) - > 0; - } - - public static List getFollowers( - EntityInterface followedEntityInterface, - String name, - EntityRelationshipDAO entityRelationshipDAO, - UserDAO userDAO) - throws IOException { - List followerIds = - entityRelationshipDAO.findFrom( - followedEntityInterface.getId().toString(), name, Relationship.FOLLOWS.ordinal(), Entity.USER); - List followers = new ArrayList<>(); - for (String followerId : followerIds) { - User user = userDAO.findEntityById(UUID.fromString(followerId), ALL); - if (followedEntityInterface.isDeleted() || !user.getDeleted()) { - followers.add(new EntityReference().withName(user.getName()).withId(user.getId()).withType("user")); - } - } - return followers; - } - @RequiredArgsConstructor public static class Fields { public static final Fields EMPTY_FIELDS = new Fields(null, null); @@ -396,7 +296,7 @@ public final class EntityUtil { return String.join(Entity.SEPARATOR, strings); } - /** Return column field name of format columnName.fieldName */ + /** Return column field name of format columnName:fieldName */ public static String getColumnField(Table table, Column column, String columnField) { // Remove table FQN from column FQN to get the local name String localColumnName = diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/events/WebhookResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/events/WebhookResourceTest.java index 884d1cd665d..262b25188aa 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/events/WebhookResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/events/WebhookResourceTest.java @@ -16,6 +16,7 @@ package org.openmetadata.catalog.resources.events; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS; import java.io.IOException; @@ -329,6 +330,7 @@ public class WebhookResourceTest extends EntityResourceTest callbackEvents = webhookCallbackResource.getEntityCallbackEvents(EventType.ENTITY_CREATED, entity); + assertTrue(callbackEvents.size() > 1); long timestamp = callbackEvents.get(0).getTimestamp(); waitAndCheckForEvents(entity, null, null, timestamp, callbackEvents, 30, 100); diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java index 73fe9aca0e1..d31515088ce 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java @@ -310,16 +310,21 @@ public final class TestUtils { } public static void existsInEntityReferenceList(List list, UUID id, boolean expectedExistsInList) { - boolean exists = false; - for (EntityReference ref : list) { - validateEntityReference(ref); - if (ref.getId().equals(id)) { - exists = true; + EntityReference ref = null; + for (EntityReference r : list) { + validateEntityReference(r); + if (r.getId().equals(id)) { + ref = r; break; } } - assertEquals( - expectedExistsInList, exists, "Entry exists in list - expected:" + expectedExistsInList + " actual:" + exists); + if (expectedExistsInList) { + assertNotNull(ref, "EntityReference does not exist for " + id); + } else { + if (ref != null) { + assertTrue(ref.getDeleted(), "EntityReference is not deleted as expected " + id); + } + } } public static void assertListNull(Object... values) {