diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java index e7ad5a4e651..0f1ef8c46cd 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java @@ -324,20 +324,16 @@ public class GlossaryTermRepository extends EntityRepository { boolean dryRun = Boolean.TRUE.equals(request.getDryRun()); GlossaryTerm term = this.get(null, glossaryTermId, getFields("id,tags")); - EntityRepository glossaryRepository = - Entity.getEntityRepository(term.getGlossary().getType()); - EntityInterface glossary = - glossaryRepository.get( - null, term.getGlossary().getId(), glossaryRepository.getFields("tags")); + // Check if the tags are mutually exclusive for the glossary - checkMutuallyExclusive(glossary.getTags()); + checkMutuallyExclusive(request.getGlossaryTags()); BulkOperationResult result = new BulkOperationResult().withDryRun(dryRun); List failures = new ArrayList<>(); List success = new ArrayList<>(); if (dryRun - && (CommonUtil.nullOrEmpty(glossary.getTags()) + && (CommonUtil.nullOrEmpty(request.getGlossaryTags()) || CommonUtil.nullOrEmpty(request.getAssets()))) { // Nothing to Validate return result @@ -369,7 +365,7 @@ public class GlossaryTermRepository extends EntityRepository { asset.getFullyQualifiedName(), FullyQualifiedName.buildHash(asset.getFullyQualifiedName()), allAssetTags, - glossary.getTags(), + request.getGlossaryTags(), false); success.add(new BulkResponse().withRequest(ref)); result.setNumberOfRowsPassed(result.getNumberOfRowsPassed() + 1); @@ -392,11 +388,11 @@ public class GlossaryTermRepository extends EntityRepository { // Apply the tags of glossary to the glossary term if (!dryRun && CommonUtil.nullOrEmpty(result.getFailedRequest()) - && (!(term.getTags().isEmpty() && glossary.getTags().isEmpty()))) { + && (!(term.getTags().isEmpty() && request.getGlossaryTags().isEmpty()))) { // Remove current entity tags in the database. It will be added back later from the merged tag // list. daoCollection.tagUsageDAO().deleteTagsByTarget(term.getFullyQualifiedName()); - applyTags(getUniqueTags(glossary.getTags()), term.getFullyQualifiedName()); + applyTags(getUniqueTags(request.getGlossaryTags()), term.getFullyQualifiedName()); searchRepository.updateEntity(term.getEntityReference()); } @@ -420,16 +416,10 @@ public class GlossaryTermRepository extends EntityRepository { UUID glossaryTermId, AddGlossaryToAssetsRequest request) { GlossaryTerm term = this.get(null, glossaryTermId, getFields("id,tags")); - EntityRepository glossaryRepository = - Entity.getEntityRepository(term.getGlossary().getType()); - EntityInterface glossary = - glossaryRepository.get( - null, term.getGlossary().getId(), glossaryRepository.getFields("tags")); - - List glossaryTagsToValidate = glossary.getTags(); + List glossaryTagsToValidate = request.getGlossaryTags(); // Check if the tags are mutually exclusive for the glossary - checkMutuallyExclusive(glossary.getTags()); + checkMutuallyExclusive(request.getGlossaryTags()); BulkOperationResult result = new BulkOperationResult().withDryRun(true); List failures = new ArrayList<>(); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryTermResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryTermResourceTest.java index 72436a447f3..a39e7e59f08 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryTermResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryTermResourceTest.java @@ -89,7 +89,6 @@ import org.openmetadata.schema.type.Include; import org.openmetadata.schema.type.TagLabel; import org.openmetadata.schema.type.TaskDetails; import org.openmetadata.schema.type.TaskStatus; -import org.openmetadata.schema.type.api.BulkOperationResult; import org.openmetadata.service.Entity; import org.openmetadata.service.governance.workflows.WorkflowHandler; import org.openmetadata.service.resources.EntityResourceTest; @@ -1457,45 +1456,6 @@ public class GlossaryTermResourceTest extends EntityResourceTest payload = - Map.of( - "assets", - List.of(new EntityReference().withId(table.getId()).withType("table")), - "dryRun", - false); - - WebTarget target = getCollection().path(String.format("/%s/assets/add", term.getId())); - TestUtils.put(target, payload, BulkOperationResult.class, OK, ADMIN_AUTH_HEADERS); - - Table updatedTable = tableResourceTest.getEntity(table.getId(), "tags", ADMIN_AUTH_HEADERS); - assertTrue( - updatedTable.getTags().stream() - .anyMatch(t -> t.getTagFQN().equals(glossaryTag.getTagFQN())), - "Table should have inherited the tag from the parent glossary"); - - tableResourceTest.deleteEntity(table.getId(), ADMIN_AUTH_HEADERS); - deleteEntity(term.getId(), ADMIN_AUTH_HEADERS); - } - public Glossary createGlossary( TestInfo test, List reviewers, List owners) throws IOException { diff --git a/openmetadata-spec/src/main/resources/json/schema/api/addGlossaryToAssetsRequest.json b/openmetadata-spec/src/main/resources/json/schema/api/addGlossaryToAssetsRequest.json index f20e43ce7b8..6997b864405 100644 --- a/openmetadata-spec/src/main/resources/json/schema/api/addGlossaryToAssetsRequest.json +++ b/openmetadata-spec/src/main/resources/json/schema/api/addGlossaryToAssetsRequest.json @@ -6,11 +6,27 @@ "type": "object", "javaType": "org.openmetadata.schema.api.AddGlossaryToAssetsRequest", "properties": { + "operation": { + "description": "Operation to be performed", + "type": "string", + "enum": [ + "AddAssets", + "AddGlossaryTags" + ] + }, "dryRun": { "description": "If true, the request will be validated but no changes will be made", "type": "boolean", "default": true }, + "glossaryTags": { + "description": "Glossary Tags to be added", + "type": "array", + "items": { + "$ref": "../type/tagLabel.json" + }, + "default": null + }, "assets": { "description": "List of assets to be created against which the glossary needs to be added.", "$ref": "../type/entityReferenceList.json" diff --git a/openmetadata-spec/src/main/resources/json/schema/api/addTagToAssetsRequest.json b/openmetadata-spec/src/main/resources/json/schema/api/addTagToAssetsRequest.json index 936caa6f89c..032f66beb0e 100644 --- a/openmetadata-spec/src/main/resources/json/schema/api/addTagToAssetsRequest.json +++ b/openmetadata-spec/src/main/resources/json/schema/api/addTagToAssetsRequest.json @@ -7,6 +7,14 @@ "javaType": "org.openmetadata.schema.api.AddTagToAssetsRequest", "javaInterfaces": ["org.openmetadata.schema.BulkAssetsRequestInterface"], "properties": { + "operation": { + "description": "Operation to be performed", + "type": "string", + "enum": [ + "AddAssets", + "AddClassificationTags" + ] + }, "dryRun": { "description": "If true, the request will be validated but no changes will be made", "type": "boolean", diff --git a/openmetadata-ui/src/main/resources/ui/src/generated/api/addGlossaryToAssetsRequest.ts b/openmetadata-ui/src/main/resources/ui/src/generated/api/addGlossaryToAssetsRequest.ts index bee3e1b03b8..d16270fdcdd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/generated/api/addGlossaryToAssetsRequest.ts +++ b/openmetadata-ui/src/main/resources/ui/src/generated/api/addGlossaryToAssetsRequest.ts @@ -22,6 +22,14 @@ export interface AddGlossaryToAssetsRequest { * If true, the request will be validated but no changes will be made */ dryRun?: boolean; + /** + * Glossary Tags to be added + */ + glossaryTags?: TagLabel[]; + /** + * Operation to be performed + */ + operation?: Operation; } /** @@ -79,3 +87,99 @@ export interface EntityReference { */ type: string; } + +/** + * This schema defines the type for labeling an entity with a Tag. + */ +export interface TagLabel { + /** + * Description for the tag label. + */ + description?: string; + /** + * Display Name that identifies this tag. + */ + displayName?: string; + /** + * Link to the tag resource. + */ + href?: string; + /** + * Label type describes how a tag label was applied. 'Manual' indicates the tag label was + * applied by a person. 'Derived' indicates a tag label was derived using the associated tag + * relationship (see Classification.json for more details). 'Propagated` indicates a tag + * label was propagated from upstream based on lineage. 'Automated' is used when a tool was + * used to determine the tag label. + */ + labelType: LabelType; + /** + * Name of the tag or glossary term. + */ + name?: string; + /** + * Label is from Tags or Glossary. + */ + source: TagSource; + /** + * 'Suggested' state is used when a tag label is suggested by users or tools. Owner of the + * entity must confirm the suggested labels before it is marked as 'Confirmed'. + */ + state: State; + style?: Style; + tagFQN: string; +} + +/** + * Label type describes how a tag label was applied. 'Manual' indicates the tag label was + * applied by a person. 'Derived' indicates a tag label was derived using the associated tag + * relationship (see Classification.json for more details). 'Propagated` indicates a tag + * label was propagated from upstream based on lineage. 'Automated' is used when a tool was + * used to determine the tag label. + */ +export enum LabelType { + Automated = "Automated", + Derived = "Derived", + Generated = "Generated", + Manual = "Manual", + Propagated = "Propagated", +} + +/** + * Label is from Tags or Glossary. + */ +export enum TagSource { + Classification = "Classification", + Glossary = "Glossary", +} + +/** + * 'Suggested' state is used when a tag label is suggested by users or tools. Owner of the + * entity must confirm the suggested labels before it is marked as 'Confirmed'. + */ +export enum State { + Confirmed = "Confirmed", + Suggested = "Suggested", +} + +/** + * UI Style is used to associate a color code and/or icon to entity to customize the look of + * that entity in UI. + */ +export interface Style { + /** + * Hex Color Code to mark an entity such as GlossaryTerm, Tag, Domain or Data Product. + */ + color?: string; + /** + * An icon to associate with GlossaryTerm, Tag, Domain or Data Product. + */ + iconURL?: string; +} + +/** + * Operation to be performed + */ +export enum Operation { + AddAssets = "AddAssets", + AddGlossaryTags = "AddGlossaryTags", +} diff --git a/openmetadata-ui/src/main/resources/ui/src/generated/api/addTagToAssetsRequest.ts b/openmetadata-ui/src/main/resources/ui/src/generated/api/addTagToAssetsRequest.ts index 729c007b9e0..8c538d38517 100644 --- a/openmetadata-ui/src/main/resources/ui/src/generated/api/addTagToAssetsRequest.ts +++ b/openmetadata-ui/src/main/resources/ui/src/generated/api/addTagToAssetsRequest.ts @@ -22,6 +22,10 @@ export interface AddTagToAssetsRequest { * If true, the request will be validated but no changes will be made */ dryRun?: boolean; + /** + * Operation to be performed + */ + operation?: Operation; } /** @@ -79,3 +83,11 @@ export interface EntityReference { */ type: string; } + +/** + * Operation to be performed + */ +export enum Operation { + AddAssets = "AddAssets", + AddClassificationTags = "AddClassificationTags", +}