This is an automated email from the ASF dual-hosted git repository.

yuqi4733 pushed a commit to branch branch-1.0
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.0 by this push:
     new 9d965f97a3 [#7916] improvement(core): Using entity store's relation 
operation to refactor tag operation (#8700)
9d965f97a3 is described below

commit 9d965f97a3240e24e908c1a59e96edede94f6372
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Sep 26 21:54:15 2025 +0800

    [#7916] improvement(core): Using entity store's relation operation to 
refactor tag operation (#8700)
    
    ### What changes were proposed in this pull request?
    
    Replace `SupportsTagOperations` with the entity store's relation
    operations
    
    ### Why are the changes needed?
    
    The entity store's relation operations are general enough, and there is
    no need to create a new interface specifically for tags.
    
    Fix: #7916
    
    ### Does this PR introduce _any_ user-facing change?
    
    N/A
    
    ### How was this patch tested?
    
    Existing UTs and ITs.
    
    ---------
    
    Co-authored-by: Mini Yu <[email protected]>
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../java/org/apache/gravitino/EntityStore.java     | 11 ---
 .../gravitino/SupportsRelationOperations.java      | 23 +++++-
 .../gravitino/storage/relational/JDBCBackend.java  | 50 ++++--------
 .../storage/relational/RelationalBackend.java      |  4 +-
 .../storage/relational/RelationalEntityStore.java  | 42 +---------
 .../storage/relational/service/TagMetaService.java | 12 ++-
 .../gravitino/tag/SupportsTagOperations.java       | 95 ----------------------
 .../java/org/apache/gravitino/tag/TagManager.java  | 62 ++++++++------
 .../relational/service/TestTagMetaService.java     | 46 ++++++-----
 9 files changed, 110 insertions(+), 235 deletions(-)

diff --git a/core/src/main/java/org/apache/gravitino/EntityStore.java 
b/core/src/main/java/org/apache/gravitino/EntityStore.java
index 79f5e12e26..c2575dc9eb 100644
--- a/core/src/main/java/org/apache/gravitino/EntityStore.java
+++ b/core/src/main/java/org/apache/gravitino/EntityStore.java
@@ -25,7 +25,6 @@ import java.util.function.Function;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.gravitino.Entity.EntityType;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
-import org.apache.gravitino.tag.SupportsTagOperations;
 import org.apache.gravitino.utils.Executable;
 
 public interface EntityStore extends Closeable {
@@ -229,16 +228,6 @@ public interface EntityStore extends Closeable {
   <R, E extends Exception> R executeInTransaction(Executable<R, E> executable)
       throws E, IOException;
 
-  /**
-   * Get the extra tag operations that are supported by the entity store.
-   *
-   * @return the tag operations object that are supported by the entity store
-   * @throws UnsupportedOperationException if the extra operations are not 
supported
-   */
-  default SupportsTagOperations tagOperations() {
-    throw new UnsupportedOperationException("tag operations are not 
supported");
-  }
-
   /**
    * Get the extra relation operations that are supported by the entity store.
    *
diff --git 
a/core/src/main/java/org/apache/gravitino/SupportsRelationOperations.java 
b/core/src/main/java/org/apache/gravitino/SupportsRelationOperations.java
index 5add56c640..7d8aca914e 100644
--- a/core/src/main/java/org/apache/gravitino/SupportsRelationOperations.java
+++ b/core/src/main/java/org/apache/gravitino/SupportsRelationOperations.java
@@ -39,7 +39,9 @@ public interface SupportsRelationOperations {
     /** Role and group relationship */
     ROLE_GROUP_REL,
     /** Policy and metadata object relationship */
-    POLICY_METADATA_OBJECT_REL
+    POLICY_METADATA_OBJECT_REL,
+    /** Metadata object to tag relationship */
+    TAG_METADATA_OBJECT_REL,
   }
 
   /**
@@ -48,7 +50,7 @@ public interface SupportsRelationOperations {
    * @param <E> The type of entities returned.
    * @param relType The type of relation.
    * @param nameIdentifier The given entity identifier.
-   * @param identType The given entity type.
+   * @param identType The entity type of parameter nameIdentifier represents.
    * @return The list of entities
    * @throws IOException When occurs storage issues, it will throw IOException.
    */
@@ -63,13 +65,28 @@ public interface SupportsRelationOperations {
    * @param <E> the type of entities returned.
    * @param relType The type of relation.
    * @param nameIdentifier The given entity identifier
-   * @param identType The given entity type.
+   * @param identType The entity type of parameter nameIdentifier represents.
    * @param allFields Some fields may have a relatively high acquisition cost, 
EntityStore provide
    *     an optional setting to avoid fetching these high-cost fields to 
improve the performance. If
    *     true, the method will fetch all the fields, Otherwise, the method 
will fetch all the fields
    *     except for high-cost fields.
    * @return The list of entities
    * @throws IOException When occurs storage issues, it will throw IOException.
+   *     <pre>
+   *  Let's see an example to illustrate how this method works.
+   *  If we want to list all the users who have a specific role, we can use 
this method as follows:
+   *
+   *    listEntitiesByRelation(ROLE_USER_REL, name_identifier_of_role, 
EntityType.ROLE);
+   *
+   *  This will return a list of User entities that are associated with the 
specified role.
+   *  Similarly, if we want to list all roles a user has, we can call:
+   *
+   *  listEntitiesByRelation(ROLE_USER_REL, name_identifier_of_user, 
EntityType.USER);
+   *
+   *  That is to say, this method is versatile and can be used to navigate 
relationships in both
+   *  directions, the start entity is determined by the identType and 
nameIdentifier parameters.
+   *  The end entity type is determined by the relType parameter and start 
entity.
+   * </pre>
    */
   <E extends Entity & HasIdentifier> List<E> listEntitiesByRelation(
       Type relType, NameIdentifier nameIdentifier, Entity.EntityType 
identType, boolean allFields)
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java 
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
index f1168d493f..3aa7402a18 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
@@ -36,7 +36,6 @@ import org.apache.gravitino.Configs;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.HasIdentifier;
-import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.SupportsRelationOperations;
@@ -455,37 +454,6 @@ public class JDBCBackend implements RelationalBackend {
     }
   }
 
-  @Override
-  public List<MetadataObject> 
listAssociatedMetadataObjectsForTag(NameIdentifier tagIdent)
-      throws IOException {
-    return 
TagMetaService.getInstance().listAssociatedMetadataObjectsForTag(tagIdent);
-  }
-
-  @Override
-  public List<TagEntity> listAssociatedTagsForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType)
-      throws NoSuchEntityException, IOException {
-    return TagMetaService.getInstance().listTagsForMetadataObject(objectIdent, 
objectType);
-  }
-
-  @Override
-  public TagEntity getTagForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType, NameIdentifier 
tagIdent)
-      throws NoSuchEntityException, IOException {
-    return TagMetaService.getInstance().getTagForMetadataObject(objectIdent, 
objectType, tagIdent);
-  }
-
-  @Override
-  public List<TagEntity> associateTagsWithMetadataObject(
-      NameIdentifier objectIdent,
-      Entity.EntityType objectType,
-      NameIdentifier[] tagsToAdd,
-      NameIdentifier[] tagsToRemove)
-      throws NoSuchEntityException, EntityAlreadyExistsException, IOException {
-    return TagMetaService.getInstance()
-        .associateTagsWithMetadataObject(objectIdent, objectType, tagsToAdd, 
tagsToRemove);
-  }
-
   @Override
   public int batchDelete(
       List<Pair<NameIdentifier, Entity.EntityType>> entitiesToDelete, boolean 
cascade)
@@ -597,6 +565,15 @@ public class JDBCBackend implements RelationalBackend {
               PolicyMetaService.getInstance()
                   .listPoliciesForMetadataObject(nameIdentifier, identType);
         }
+
+      case TAG_METADATA_OBJECT_REL:
+        if (identType == Entity.EntityType.TAG) {
+          return (List<E>)
+              
TagMetaService.getInstance().listAssociatedMetadataObjectsForTag(nameIdentifier);
+        } else {
+          return (List<E>)
+              
TagMetaService.getInstance().listTagsForMetadataObject(nameIdentifier, 
identType);
+        }
       default:
         throw new IllegalArgumentException(
             String.format("Doesn't support the relation type %s", relType));
@@ -635,6 +612,11 @@ public class JDBCBackend implements RelationalBackend {
             PolicyMetaService.getInstance()
                 .associatePoliciesWithMetadataObject(
                     srcEntityIdent, srcEntityType, destEntitiesToAdd, 
destEntitiesToRemove);
+      case TAG_METADATA_OBJECT_REL:
+        return (List<E>)
+            TagMetaService.getInstance()
+                .associateTagsWithMetadataObject(
+                    srcEntityIdent, srcEntityType, destEntitiesToAdd, 
destEntitiesToRemove);
       default:
         throw new IllegalArgumentException(
             String.format("Doesn't support the relation type %s", relType));
@@ -653,6 +635,10 @@ public class JDBCBackend implements RelationalBackend {
         return (E)
             PolicyMetaService.getInstance()
                 .getPolicyForMetadataObject(srcIdentifier, srcType, 
destEntityIdent);
+      case TAG_METADATA_OBJECT_REL:
+        return (E)
+            TagMetaService.getInstance()
+                .getTagForMetadataObject(srcIdentifier, srcType, 
destEntityIdent);
       default:
         throw new IllegalArgumentException(
             String.format("Doesn't support the relation type %s", relType));
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
index 42c21e9a5d..037d5256e0 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
@@ -31,11 +31,9 @@ import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.SupportsRelationOperations;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
-import org.apache.gravitino.tag.SupportsTagOperations;
 
 /** Interface defining the operations for a Relation Backend. */
-public interface RelationalBackend
-    extends Closeable, SupportsTagOperations, SupportsRelationOperations {
+public interface RelationalBackend extends Closeable, 
SupportsRelationOperations {
 
   /**
    * Initializes the Relational Backend environment with the provided 
configuration.
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
index 15bf0eabd6..790624bc12 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
@@ -32,7 +32,6 @@ import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.EntityStore;
 import org.apache.gravitino.HasIdentifier;
-import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.SupportsRelationOperations;
@@ -41,8 +40,6 @@ import org.apache.gravitino.cache.EntityCache;
 import org.apache.gravitino.cache.EntityCacheRelationKey;
 import org.apache.gravitino.cache.NoOpsCache;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
-import org.apache.gravitino.meta.TagEntity;
-import org.apache.gravitino.tag.SupportsTagOperations;
 import org.apache.gravitino.utils.Executable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,8 +49,7 @@ import org.slf4j.LoggerFactory;
  * MySQL, PostgreSQL, etc. If you want to use a different backend, you can 
implement the {@link
  * RelationalBackend} interface
  */
-public class RelationalEntityStore
-    implements EntityStore, SupportsTagOperations, SupportsRelationOperations {
+public class RelationalEntityStore implements EntityStore, 
SupportsRelationOperations {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(RelationalEntityStore.class);
   public static final ImmutableMap<String, String> RELATIONAL_BACKENDS =
       ImmutableMap.of(
@@ -166,47 +162,11 @@ public class RelationalEntityStore
     backend.close();
   }
 
-  @Override
-  public SupportsTagOperations tagOperations() {
-    return this;
-  }
-
   @Override
   public SupportsRelationOperations relationOperations() {
     return this;
   }
 
-  @Override
-  public List<MetadataObject> 
listAssociatedMetadataObjectsForTag(NameIdentifier tagIdent)
-      throws IOException {
-    return backend.listAssociatedMetadataObjectsForTag(tagIdent);
-  }
-
-  @Override
-  public List<TagEntity> listAssociatedTagsForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType)
-      throws NoSuchEntityException, IOException {
-    return backend.listAssociatedTagsForMetadataObject(objectIdent, 
objectType);
-  }
-
-  @Override
-  public TagEntity getTagForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType, NameIdentifier 
tagIdent)
-      throws NoSuchEntityException, IOException {
-    return backend.getTagForMetadataObject(objectIdent, objectType, tagIdent);
-  }
-
-  @Override
-  public List<TagEntity> associateTagsWithMetadataObject(
-      NameIdentifier objectIdent,
-      Entity.EntityType objectType,
-      NameIdentifier[] tagsToAdd,
-      NameIdentifier[] tagsToRemove)
-      throws NoSuchEntityException, EntityAlreadyExistsException, IOException {
-    return backend.associateTagsWithMetadataObject(
-        objectIdent, objectType, tagsToAdd, tagsToRemove);
-  }
-
   @Override
   public <E extends Entity & HasIdentifier> List<E> listEntitiesByRelation(
       Type relType, NameIdentifier nameIdentifier, Entity.EntityType 
identType, boolean allFields)
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
index c5481357df..a84fb39185 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
@@ -32,11 +32,11 @@ import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.HasIdentifier;
 import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.MetadataObjects;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
 import org.apache.gravitino.exceptions.NoSuchTagException;
+import org.apache.gravitino.meta.GenericEntity;
 import org.apache.gravitino.meta.TagEntity;
 import org.apache.gravitino.storage.relational.mapper.TagMetaMapper;
 import 
org.apache.gravitino.storage.relational.mapper.TagMetadataObjectRelMapper;
@@ -218,7 +218,7 @@ public class TagMetaService {
     return POConverters.fromTagPO(tagPO, NamespaceUtil.ofTag(metalake));
   }
 
-  public List<MetadataObject> 
listAssociatedMetadataObjectsForTag(NameIdentifier tagIdent)
+  public List<GenericEntity> 
listAssociatedMetadataObjectsForTag(NameIdentifier tagIdent)
       throws IOException {
     String metalakeName = tagIdent.namespace().level(0);
     String tagName = tagIdent.name();
@@ -230,7 +230,7 @@ public class TagMetaService {
               mapper ->
                   
mapper.listTagMetadataObjectRelsByMetalakeAndTagName(metalakeName, tagName));
 
-      List<MetadataObject> metadataObjects = Lists.newArrayList();
+      List<GenericEntity> metadataObjects = Lists.newArrayList();
       Map<String, List<TagMetadataObjectRelPO>> tagMetadataObjectRelPOsByType =
           tagMetadataObjectRelPOs.stream()
               
.collect(Collectors.groupingBy(TagMetadataObjectRelPO::getMetadataObjectType));
@@ -256,7 +256,11 @@ public class TagMetaService {
           // return null, we should skip this metadata object.
           if (fullName != null) {
             metadataObjects.add(
-                MetadataObjects.parse(fullName, 
MetadataObject.Type.valueOf(metadataObjectType)));
+                GenericEntity.builder()
+                    .withName(fullName)
+                    
.withEntityType(Entity.EntityType.valueOf(metadataObjectType))
+                    .withId(metadataObjectName.getKey())
+                    .build());
           }
         }
       }
diff --git 
a/core/src/main/java/org/apache/gravitino/tag/SupportsTagOperations.java 
b/core/src/main/java/org/apache/gravitino/tag/SupportsTagOperations.java
deleted file mode 100644
index eaea94e356..0000000000
--- a/core/src/main/java/org/apache/gravitino/tag/SupportsTagOperations.java
+++ /dev/null
@@ -1,95 +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
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.gravitino.tag;
-
-import java.io.IOException;
-import java.util.List;
-import org.apache.gravitino.Entity;
-import org.apache.gravitino.EntityAlreadyExistsException;
-import org.apache.gravitino.EntityStore;
-import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.NameIdentifier;
-import org.apache.gravitino.exceptions.NoSuchEntityException;
-import org.apache.gravitino.meta.TagEntity;
-
-/**
- * An interface to support extra tag operations, this interface should be 
mixed with {@link
- * EntityStore} to provide extra operations.
- *
- * <p>Any operations that can be done by the entity store should be added here.
- */
-public interface SupportsTagOperations {
-
-  /**
-   * List all the metadata objects that are associated with the given tag.
-   *
-   * @param tagIdent The identifier of the tag.
-   * @return The list of metadata objects associated with the given tag.
-   * @throws IOException If an error occurs while accessing the entity store.
-   */
-  List<MetadataObject> listAssociatedMetadataObjectsForTag(NameIdentifier 
tagIdent)
-      throws IOException;
-
-  /**
-   * List all the tags that are associated with the given metadata object.
-   *
-   * @param objectIdent The identifier of the metadata object.
-   * @param objectType The type of the metadata object.
-   * @return The list of tags associated with the given metadata object.
-   * @throws NoSuchEntityException if the metadata object does not exist.
-   * @throws IOException If an error occurs while accessing the entity store.
-   */
-  List<TagEntity> listAssociatedTagsForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType)
-      throws NoSuchEntityException, IOException;
-
-  /**
-   * Get the tag with the given identifier that is associated with the given 
metadata object.
-   *
-   * @param objectIdent The identifier of the metadata object.
-   * @param objectType The type of the metadata object.
-   * @param tagIdent The identifier of the tag.
-   * @return The tag associated with the metadata object.
-   * @throws NoSuchEntityException if the metadata object does not exist or 
the tag is not
-   *     associated to the metadata object.
-   * @throws IOException If an error occurs while accessing the entity store.
-   */
-  TagEntity getTagForMetadataObject(
-      NameIdentifier objectIdent, Entity.EntityType objectType, NameIdentifier 
tagIdent)
-      throws NoSuchEntityException, IOException;
-
-  /**
-   * Associate the given tags with the given metadata object.
-   *
-   * @param objectIdent The identifier of the metadata object.
-   * @param objectType The type of the metadata object.
-   * @param tagsToAdd The name of tags to associate with the metadata object.
-   * @param tagsToRemove the name of tags to remove from the metadata object.
-   * @return The list of tags associated with the metadata object after the 
operation.
-   * @throws NoSuchEntityException if the metadata object does not exist.
-   * @throws EntityAlreadyExistsException if tags already associated with the 
metadata object.
-   * @throws IOException If an error occurs while accessing the entity store.
-   */
-  List<TagEntity> associateTagsWithMetadataObject(
-      NameIdentifier objectIdent,
-      Entity.EntityType objectType,
-      NameIdentifier[] tagsToAdd,
-      NameIdentifier[] tagsToRemove)
-      throws NoSuchEntityException, EntityAlreadyExistsException, IOException;
-}
diff --git a/core/src/main/java/org/apache/gravitino/tag/TagManager.java 
b/core/src/main/java/org/apache/gravitino/tag/TagManager.java
index 9cfed65027..18d258c1ee 100644
--- a/core/src/main/java/org/apache/gravitino/tag/TagManager.java
+++ b/core/src/main/java/org/apache/gravitino/tag/TagManager.java
@@ -27,6 +27,7 @@ import java.io.IOException;
 import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.gravitino.Entity;
@@ -34,6 +35,7 @@ import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.EntityStore;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.SupportsRelationOperations;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
 import org.apache.gravitino.exceptions.NoSuchMetadataObjectException;
 import org.apache.gravitino.exceptions.NoSuchTagException;
@@ -43,8 +45,10 @@ import 
org.apache.gravitino.exceptions.TagAlreadyExistsException;
 import org.apache.gravitino.lock.LockType;
 import org.apache.gravitino.lock.TreeLockUtils;
 import org.apache.gravitino.meta.AuditInfo;
+import org.apache.gravitino.meta.GenericEntity;
 import org.apache.gravitino.meta.TagEntity;
 import org.apache.gravitino.storage.IdGenerator;
+import org.apache.gravitino.storage.relational.service.MetadataObjectService;
 import org.apache.gravitino.utils.MetadataObjectUtil;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 import org.apache.gravitino.utils.NamespaceUtil;
@@ -60,19 +64,7 @@ public class TagManager implements TagDispatcher {
 
   private final EntityStore entityStore;
 
-  private final SupportsTagOperations supportsTagOperations;
-
   public TagManager(IdGenerator idGenerator, EntityStore entityStore) {
-    if (!(entityStore instanceof SupportsTagOperations)) {
-      String errorMsg =
-          "TagManager cannot run with entity store that does not support tag 
operations, "
-              + "please configure the entity store to use relational entity 
store and restart the Gravitino server";
-      LOG.error(errorMsg);
-      throw new RuntimeException(errorMsg);
-    }
-
-    this.supportsTagOperations = entityStore.tagOperations();
-
     this.idGenerator = idGenerator;
     this.entityStore = entityStore;
   }
@@ -212,8 +204,14 @@ public class TagManager implements TagDispatcher {
                   "Tag with name %s under metalake %s does not exist", name, 
metalake);
             }
 
-            return supportsTagOperations
-                .listAssociatedMetadataObjectsForTag(tagId)
+            List<GenericEntity> entities =
+                entityStore
+                    .relationOperations()
+                    .listEntitiesByRelation(
+                        
SupportsRelationOperations.Type.TAG_METADATA_OBJECT_REL,
+                        tagId,
+                        Entity.EntityType.TAG);
+            return MetadataObjectService.fromGenericEntities(entities)
                 .toArray(new MetadataObject[0]);
           } catch (IOException e) {
             LOG.error("Failed to list metadata objects for tag {}", name, e);
@@ -242,9 +240,14 @@ public class TagManager implements TagDispatcher {
         () -> {
           try {
             checkMetalake(NameIdentifier.of(metalake), entityStore);
-            return supportsTagOperations
-                .listAssociatedTagsForMetadataObject(entityIdent, entityType)
-                .toArray(new Tag[0]);
+            List<TagEntity> tags =
+                entityStore
+                    .relationOperations()
+                    .listEntitiesByRelation(
+                        
SupportsRelationOperations.Type.TAG_METADATA_OBJECT_REL,
+                        entityIdent,
+                        entityType);
+            return tags.toArray(new Tag[0]);
           } catch (NoSuchEntityException e) {
             throw new NoSuchMetadataObjectException(
                 e, "Failed to list tags for metadata object %s due to not 
found", metadataObject);
@@ -269,7 +272,13 @@ public class TagManager implements TagDispatcher {
         () -> {
           try {
             checkMetalake(NameIdentifier.of(metalake), entityStore);
-            return supportsTagOperations.getTagForMetadataObject(entityIdent, 
entityType, tagIdent);
+            return entityStore
+                .relationOperations()
+                .getEntityByRelation(
+                    SupportsRelationOperations.Type.TAG_METADATA_OBJECT_REL,
+                    entityIdent,
+                    entityType,
+                    tagIdent);
           } catch (NoSuchEntityException e) {
             if (e.getMessage().contains("No such tag entity")) {
               throw new NoSuchTagException(
@@ -325,12 +334,17 @@ public class TagManager implements TagDispatcher {
                 LockType.WRITE,
                 () -> {
                   try {
-                    return supportsTagOperations
-                        .associateTagsWithMetadataObject(
-                            entityIdent, entityType, tagsToAddIdent, 
tagsToRemoveIdent)
-                        .stream()
-                        .map(Tag::name)
-                        .toArray(String[]::new);
+                    List<TagEntity> tags =
+                        entityStore
+                            .relationOperations()
+                            .updateEntityRelations(
+                                
SupportsRelationOperations.Type.TAG_METADATA_OBJECT_REL,
+                                entityIdent,
+                                entityType,
+                                tagsToAddIdent,
+                                tagsToRemoveIdent);
+
+                    return tags.stream().map(Tag::name).toArray(String[]::new);
                   } catch (NoSuchEntityException e) {
                     throw new NoSuchMetadataObjectException(
                         e,
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java
index 13c4f4620f..91d40cb597 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java
@@ -26,8 +26,6 @@ import java.util.List;
 import java.util.Map;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
-import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.MetadataObjects;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
 import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -36,6 +34,7 @@ import org.apache.gravitino.meta.BaseMetalake;
 import org.apache.gravitino.meta.CatalogEntity;
 import org.apache.gravitino.meta.ColumnEntity;
 import org.apache.gravitino.meta.FilesetEntity;
+import org.apache.gravitino.meta.GenericEntity;
 import org.apache.gravitino.meta.ModelEntity;
 import org.apache.gravitino.meta.SchemaEntity;
 import org.apache.gravitino.meta.TableEntity;
@@ -593,6 +592,11 @@ public class TestTagMetaService extends TestJDBCBackend {
     Assertions.assertTrue(e.getMessage().contains("No such tag entity: tag4"));
   }
 
+  private boolean containsGenericEntity(
+      List<GenericEntity> genericEntities, String name, Entity.EntityType 
entityType) {
+    return genericEntities.stream().anyMatch(e -> e.name().equals(name) && 
e.type() == entityType);
+  }
+
   @Test
   public void testListAssociatedMetadataObjectsForTag() throws IOException {
     testAssociateAndDisassociateTagsWithMetadataObject();
@@ -600,37 +604,35 @@ public class TestTagMetaService extends TestJDBCBackend {
     TagMetaService tagMetaService = TagMetaService.getInstance();
 
     // Test list associated metadata objects for tag2
-    List<MetadataObject> metadataObjects =
+    List<GenericEntity> metadataObjects =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag2"));
 
     Assertions.assertEquals(3, metadataObjects.size());
     Assertions.assertTrue(
-        metadataObjects.contains(MetadataObjects.parse("catalog1", 
MetadataObject.Type.CATALOG)));
+        containsGenericEntity(metadataObjects, "catalog1", 
Entity.EntityType.CATALOG));
     Assertions.assertTrue(
-        metadataObjects.contains(
-            MetadataObjects.parse("catalog1.schema1", 
MetadataObject.Type.SCHEMA)));
+        containsGenericEntity(metadataObjects, "catalog1.schema1", 
Entity.EntityType.SCHEMA));
     Assertions.assertTrue(
-        metadataObjects.contains(
-            MetadataObjects.parse("catalog1.schema1.table1", 
MetadataObject.Type.TABLE)));
+        containsGenericEntity(metadataObjects, "catalog1.schema1.table1", 
Entity.EntityType.TABLE));
 
     // Test list associated metadata objects for tag3
-    List<MetadataObject> metadataObjects1 =
+    List<GenericEntity> metadataObjects1 =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag3"));
 
     Assertions.assertEquals(3, metadataObjects1.size());
+
     Assertions.assertTrue(
-        metadataObjects1.contains(MetadataObjects.parse("catalog1", 
MetadataObject.Type.CATALOG)));
+        containsGenericEntity(metadataObjects1, "catalog1", 
Entity.EntityType.CATALOG));
     Assertions.assertTrue(
-        metadataObjects1.contains(
-            MetadataObjects.parse("catalog1.schema1", 
MetadataObject.Type.SCHEMA)));
+        containsGenericEntity(metadataObjects1, "catalog1.schema1", 
Entity.EntityType.SCHEMA));
     Assertions.assertTrue(
-        metadataObjects1.contains(
-            MetadataObjects.parse("catalog1.schema1.table1", 
MetadataObject.Type.TABLE)));
+        containsGenericEntity(
+            metadataObjects1, "catalog1.schema1.table1", 
Entity.EntityType.TABLE));
 
     // Test list associated metadata objects for non-existent tag
-    List<MetadataObject> metadataObjects2 =
+    List<GenericEntity> metadataObjects2 =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag4"));
     Assertions.assertEquals(0, metadataObjects2.size());
@@ -641,31 +643,31 @@ public class TestTagMetaService extends TestJDBCBackend {
         Entity.EntityType.TABLE,
         false);
 
-    List<MetadataObject> metadataObjects3 =
+    List<GenericEntity> metadataObjects3 =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag2"));
 
     Assertions.assertEquals(2, metadataObjects3.size());
+
     Assertions.assertTrue(
-        metadataObjects3.contains(MetadataObjects.parse("catalog1", 
MetadataObject.Type.CATALOG)));
+        containsGenericEntity(metadataObjects3, "catalog1", 
Entity.EntityType.CATALOG));
     Assertions.assertTrue(
-        metadataObjects3.contains(
-            MetadataObjects.parse("catalog1.schema1", 
MetadataObject.Type.SCHEMA)));
+        containsGenericEntity(metadataObjects3, "catalog1.schema1", 
Entity.EntityType.SCHEMA));
 
     backend.delete(
         NameIdentifier.of(metalakeName, "catalog1", "schema1"), 
Entity.EntityType.SCHEMA, false);
 
-    List<MetadataObject> metadataObjects4 =
+    List<GenericEntity> metadataObjects4 =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag2"));
 
     Assertions.assertEquals(1, metadataObjects4.size());
     Assertions.assertTrue(
-        metadataObjects4.contains(MetadataObjects.parse("catalog1", 
MetadataObject.Type.CATALOG)));
+        containsGenericEntity(metadataObjects4, "catalog1", 
Entity.EntityType.CATALOG));
 
     backend.delete(NameIdentifier.of(metalakeName, "catalog1"), 
Entity.EntityType.CATALOG, false);
 
-    List<MetadataObject> metadataObjects5 =
+    List<GenericEntity> metadataObjects5 =
         tagMetaService.listAssociatedMetadataObjectsForTag(
             NameIdentifierUtil.ofTag(metalakeName, "tag2"));
 

Reply via email to