From c56e78f3f2532ba8952d64a4d6e6f1b2dd26f284 Mon Sep 17 00:00:00 2001 From: Suresh Srinivas Date: Wed, 2 Mar 2022 01:02:16 -0800 Subject: [PATCH] Fixes #3069 - Add PATCH support Glossary and GlossaryTerms (#3070) --- .../catalog/jdbi3/EntityRepository.java | 100 ++++++++++++++++++ .../catalog/jdbi3/GlossaryRepository.java | 50 +++++++-- .../catalog/jdbi3/GlossaryTermRepository.java | 37 ++++++- .../catalog/jdbi3/TeamRepository.java | 60 ++--------- .../catalog/jdbi3/UserRepository.java | 2 +- .../resources/glossary/GlossaryResource.java | 3 +- .../catalog/resources/teams/UserResource.java | 2 +- .../json/schema/api/data/createGlossary.json | 4 +- .../json/schema/entity/data/glossary.json | 6 +- .../json/schema/entity/data/glossaryTerm.json | 6 +- .../catalog/resources/EntityResourceTest.java | 9 +- .../glossary/GlossaryResourceTest.java | 36 ++++++- .../glossary/GlossaryTermResourceTest.java | 40 ++++++- 13 files changed, 272 insertions(+), 83 deletions(-) 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 c4a536029e0..a0cf4784085 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 @@ -408,6 +408,7 @@ public abstract class EntityRepository { T original = setFields(dao.findEntityById(id), patchFields); // Apply JSON patch to the original entity to get the updated entity + System.out.println("XXX patch is " + patch); T updated = JsonUtils.applyPatch(original, patch, entityClass); EntityInterface updatedEntity = getEntityInterface(updated); updatedEntity.setUpdateDetails(user, System.currentTimeMillis()); @@ -861,6 +862,14 @@ public abstract class EntityRepository { return daoCollection.relationshipDAO().insert(fromId, toId, fromEntity, toEntity, relationship.ordinal()); } + public int addBidirectionalRelationship( + UUID fromId, UUID toId, String fromEntity, String toEntity, Relationship relationship) { + if (fromId.compareTo(toId) < 0) { + return daoCollection.relationshipDAO().insert(fromId, toId, fromEntity, toEntity, relationship.ordinal()); + } + return daoCollection.relationshipDAO().insert(toId, fromId, toEntity, fromEntity, relationship.ordinal()); + } + public void setOwner(UUID ownedEntityId, String ownedEntityType, EntityReference owner) { // Add relationship owner --- owns ---> ownedEntity if (owner != null) { @@ -891,6 +900,26 @@ public abstract class EntityRepository { .findTo(fromId.toString(), fromEntity, relationship.ordinal(), toEntity, deleted); } + public void validateUsers(List entityReferences) throws IOException { + if (entityReferences != null) { + entityReferences.sort(EntityUtil.compareEntityReference); + for (EntityReference entityReference : entityReferences) { + EntityReference ref = daoCollection.userDAO().findEntityReferenceById(entityReference.getId()); + entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName()); + } + } + } + + public void validateRoles(List entityReferences) throws IOException { + if (entityReferences != null) { + entityReferences.sort(EntityUtil.compareEntityReference); + for (EntityReference entityReference : entityReferences) { + EntityReference ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId()); + entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName()); + } + } + } + enum Operation { PUT, PATCH, @@ -1135,6 +1164,77 @@ public abstract class EntityRepository { return !addedItems.isEmpty() || !deletedItems.isEmpty(); } + /** + * Remove `fromEntityType:fromId` -- `relationType` ---> `toEntityType:origToRefs` Add `fromEntityType:fromId` -- + * `relationType` ---> `toEntityType:updatedToRefs` and record it as change for entity field `field`. + */ + public final void updateToRelationships( + String field, + String fromEntityType, + UUID fromId, + Relationship relationshipType, + String toEntityType, + List origToRefs, + List updatedToRefs) + throws JsonProcessingException { + List added = new ArrayList<>(); + List deleted = new ArrayList<>(); + if (!recordListChange(field, origToRefs, updatedToRefs, added, deleted, entityReferenceMatch)) { + // No changes between original and updated. + return; + } + // Remove relationships from original + daoCollection + .relationshipDAO() + .deleteFrom(fromId.toString(), fromEntityType, relationshipType.ordinal(), toEntityType); + // Add relationships from updated + for (EntityReference ref : updatedToRefs) { + System.out.println( + String.format( + "XXX relationship %s:%s to %s:%s of type %s", + fromEntityType, fromId, toEntityType, ref.getId(), relationshipType)); + addRelationship(fromId, ref.getId(), fromEntityType, toEntityType, relationshipType); + } + updatedToRefs.sort(EntityUtil.compareEntityReference); + origToRefs.sort(EntityUtil.compareEntityReference); + } + + /** + * Remove `fromEntityType:origFromRefs` -- `relationType` ---> `toEntityType:toId` Add + * `fromEntityType:updatedFromRefs` -- `relationType` ---> `toEntityType:toId` and record it as change for entity + * field `field`. + */ + public final void updateFromRelationships( + String field, + String fromEntityType, + List originFromRefs, + List updatedFromRefs, + Relationship relationshipType, + String toEntityType, + UUID toId) + throws JsonProcessingException { + List added = new ArrayList<>(); + List deleted = new ArrayList<>(); + if (!recordListChange(field, originFromRefs, updatedFromRefs, added, deleted, entityReferenceMatch)) { + // No changes between original and updated. + return; + } + // Remove relationships from original + daoCollection + .relationshipDAO() + .deleteTo(toId.toString(), fromEntityType, relationshipType.ordinal(), toEntityType); + // Add relationships from updated + for (EntityReference ref : updatedFromRefs) { + System.out.println( + String.format( + "XXX relationship %s:%s to %s:%s of type %s", + fromEntityType, ref, toEntityType, toId, relationshipType)); + addRelationship(ref.getId(), toId, fromEntityType, toEntityType, relationshipType); + } + updatedFromRefs.sort(EntityUtil.compareEntityReference); + originFromRefs.sort(EntityUtil.compareEntityReference); + } + public final void storeUpdate() throws IOException { if (updateVersion(original.getVersion())) { // Update changed the entity version storeOldVersion(); // Store old version for listing previous versions of the entity 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 450727de6b4..6e9a8ae00c9 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 @@ -19,10 +19,13 @@ package org.openmetadata.catalog.jdbi3; import static org.openmetadata.catalog.Entity.FIELD_OWNER; import static org.openmetadata.catalog.Entity.helper; +import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; import java.net.URI; import java.text.ParseException; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.UUID; import org.jdbi.v3.sqlobject.transaction.Transaction; import org.openmetadata.catalog.Entity; @@ -30,6 +33,7 @@ import org.openmetadata.catalog.entity.data.Glossary; import org.openmetadata.catalog.resources.glossary.GlossaryResource; import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.Relationship; import org.openmetadata.catalog.type.TagLabel; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; @@ -37,8 +41,8 @@ import org.openmetadata.catalog.util.EntityUtil.Fields; import org.openmetadata.catalog.util.JsonUtils; public class GlossaryRepository extends EntityRepository { - private static final Fields GLOSSARY_UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags"); - private static final Fields GLOSSARY_PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags"); + private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags,reviewers"); + private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags,reviewers"); public GlossaryRepository(CollectionDAO dao) { super( @@ -47,8 +51,8 @@ public class GlossaryRepository extends EntityRepository { Glossary.class, dao.glossaryDAO(), dao, - GLOSSARY_PATCH_FIELDS, - GLOSSARY_UPDATE_FIELDS, + PATCH_FIELDS, + UPDATE_FIELDS, true, true, false); @@ -63,13 +67,14 @@ public class GlossaryRepository extends EntityRepository { public Glossary setFields(Glossary glossary, Fields fields) throws IOException, ParseException { glossary.setOwner(fields.contains(FIELD_OWNER) ? getOwner(glossary) : null); glossary.setTags(fields.contains("tags") ? getTags(glossary.getName()) : null); + glossary.setReviewers(fields.contains("reviewers") ? getReviewers(glossary) : null); return glossary; } @Override public void prepare(Glossary glossary) throws IOException, ParseException { glossary.setOwner(helper(glossary).validateOwnerOrNull()); - // TODO validate reviewers + validateUsers(glossary.getReviewers()); glossary.setTags(EntityUtil.addDerivedTags(daoCollection.tagDAO(), glossary.getTags())); } @@ -78,7 +83,7 @@ public class GlossaryRepository extends EntityRepository { // Relationships and fields such as href are derived and not stored as part of json EntityReference owner = glossary.getOwner(); List tags = glossary.getTags(); - // TODO Add relationships for reviewers + List reviewers = glossary.getReviewers(); // Don't store owner, href and tags as JSON. Build it on the fly based on relationships glossary.withOwner(null).withHref(null).withTags(null); @@ -90,14 +95,16 @@ public class GlossaryRepository extends EntityRepository { } // Restore the relationships - glossary.withOwner(owner).withTags(tags); + glossary.withOwner(owner).withTags(tags).withReviewers(reviewers); } @Override public void storeRelationships(Glossary glossary) { - // TODO Add relationships for related terms, and reviewers setOwner(glossary, glossary.getOwner()); applyTags(glossary); + for (EntityReference reviewer : Optional.ofNullable(glossary.getReviewers()).orElse(Collections.emptyList())) { + addRelationship(reviewer.getId(), glossary.getId(), Entity.USER, Entity.GLOSSARY, Relationship.REVIEWS); + } } @Override @@ -110,6 +117,13 @@ public class GlossaryRepository extends EntityRepository { return new GlossaryUpdater(original, updated, operation); } + private List getReviewers(Glossary entity) throws IOException { + List ids = + findFrom(entity.getId(), Entity.GLOSSARY, Relationship.REVIEWS, Entity.USER, entity.getDeleted()); + System.out.println("XXX reviewers for " + entity.getId() + " " + ids); + return EntityUtil.populateEntityReferences(ids, Entity.USER); + } + public static class GlossaryEntityInterface implements EntityInterface { private final Glossary entity; @@ -260,5 +274,25 @@ public class GlossaryRepository extends EntityRepository { public GlossaryUpdater(Glossary original, Glossary updated, Operation operation) { super(original, updated, operation); } + + @Override + public void entitySpecificUpdate() throws IOException, ParseException { + updateReviewers(original.getEntity(), updated.getEntity()); + } + + private void updateReviewers(Glossary origGlossary, Glossary updatedGlossary) throws JsonProcessingException { + List origUsers = + Optional.ofNullable(origGlossary.getReviewers()).orElse(Collections.emptyList()); + List updatedUsers = + Optional.ofNullable(updatedGlossary.getReviewers()).orElse(Collections.emptyList()); + updateFromRelationships( + "reviewers", + Entity.USER, + origUsers, + updatedUsers, + Relationship.REVIEWS, + Entity.GLOSSARY, + origGlossary.getId()); + } } } 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 fd880143f8d..b2e78d71880 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 @@ -16,9 +16,13 @@ package org.openmetadata.catalog.jdbi3; +import static org.openmetadata.catalog.util.EntityUtil.stringMatch; + +import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; import java.net.URI; import java.text.ParseException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -39,8 +43,8 @@ import org.openmetadata.catalog.util.JsonUtils; @Slf4j public class GlossaryTermRepository extends EntityRepository { - private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags"); - private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags"); + private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags,reviewers"); + private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags,reviewers"); public GlossaryTermRepository(CollectionDAO dao) { super( @@ -166,11 +170,10 @@ public class GlossaryTermRepository extends EntityRepository { } for (EntityReference relTerm : Optional.ofNullable(entity.getRelatedTerms()).orElse(Collections.emptyList())) { // Make this bidirectional relationship - addRelationship( + addBidirectionalRelationship( entity.getId(), relTerm.getId(), Entity.GLOSSARY_TERM, Entity.GLOSSARY_TERM, Relationship.RELATED_TO); } for (EntityReference reviewer : Optional.ofNullable(entity.getReviewers()).orElse(Collections.emptyList())) { - // Make this bidirectional relationship addRelationship(reviewer.getId(), entity.getId(), Entity.USER, Entity.GLOSSARY_TERM, Relationship.REVIEWS); } @@ -349,7 +352,31 @@ public class GlossaryTermRepository extends EntityRepository { @Override public void entitySpecificUpdate() throws IOException { - // TODO + updateSynonyms(original.getEntity(), updated.getEntity()); + updateReviewers(original.getEntity(), updated.getEntity()); + } + + private void updateSynonyms(GlossaryTerm origTerm, GlossaryTerm updatedTerm) throws JsonProcessingException { + List origSynonyms = Optional.ofNullable(origTerm.getSynonyms()).orElse(Collections.emptyList()); + List updatedSynonyms = Optional.ofNullable(updatedTerm.getSynonyms()).orElse(Collections.emptyList()); + + List added = new ArrayList<>(); + List deleted = new ArrayList<>(); + recordListChange("synonyms", origSynonyms, updatedSynonyms, added, deleted, stringMatch); + } + + private void updateReviewers(GlossaryTerm origTerm, GlossaryTerm updatedTerm) throws JsonProcessingException { + List origUsers = Optional.ofNullable(origTerm.getReviewers()).orElse(Collections.emptyList()); + List updatedUsers = + Optional.ofNullable(updatedTerm.getReviewers()).orElse(Collections.emptyList()); + updateFromRelationships( + "reviewers", + Entity.USER, + origUsers, + updatedUsers, + Relationship.REVIEWS, + Entity.GLOSSARY_TERM, + origTerm.getId()); } } } 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 d924f00811e..c8cfbebb54b 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 @@ -13,7 +13,6 @@ package org.openmetadata.catalog.jdbi3; -import static org.openmetadata.catalog.util.EntityUtil.entityReferenceMatch; import static org.openmetadata.catalog.util.EntityUtil.toBoolean; import com.fasterxml.jackson.core.JsonProcessingException; @@ -63,26 +62,6 @@ public class TeamRepository extends EntityRepository { return entityReferences; } - public void validateEntityReferences(List entityReferences, String entityType) throws IOException { - if (entityReferences != null) { - entityReferences.sort(EntityUtil.compareEntityReference); - for (EntityReference entityReference : entityReferences) { - EntityReference ref; - switch (entityType) { - case Entity.USER: - ref = daoCollection.userDAO().findEntityReferenceById(entityReference.getId()); - break; - case Entity.ROLE: - ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId()); - break; - default: - throw new IllegalArgumentException("Unsupported entity reference for validation"); - } - entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName()); - } - } - } - @Override public Team setFields(Team team, Fields fields) throws IOException { if (!fields.contains("profile")) { @@ -107,8 +86,8 @@ public class TeamRepository extends EntityRepository { @Override public void prepare(Team team) throws IOException { - validateEntityReferences(team.getUsers(), Entity.USER); - validateEntityReferences(team.getDefaultRoles(), Entity.ROLE); + validateUsers(team.getUsers()); + validateRoles(team.getDefaultRoles()); } @Override @@ -297,8 +276,8 @@ public class TeamRepository extends EntityRepository { private void updateUsers(Team origTeam, Team updatedTeam) throws JsonProcessingException { List origUsers = Optional.ofNullable(origTeam.getUsers()).orElse(Collections.emptyList()); List updatedUsers = Optional.ofNullable(updatedTeam.getUsers()).orElse(Collections.emptyList()); - updateEntityRelationships( - "users", origTeam.getId(), updatedTeam.getId(), Relationship.HAS, Entity.USER, origUsers, updatedUsers); + updateToRelationships( + "users", Entity.TEAM, origTeam.getId(), Relationship.HAS, Entity.USER, origUsers, updatedUsers); } private void updateDefaultRoles(Team origTeam, Team updatedTeam) throws JsonProcessingException { @@ -306,41 +285,14 @@ public class TeamRepository extends EntityRepository { Optional.ofNullable(origTeam.getDefaultRoles()).orElse(Collections.emptyList()); List updatedDefaultRoles = Optional.ofNullable(updatedTeam.getDefaultRoles()).orElse(Collections.emptyList()); - updateEntityRelationships( + updateToRelationships( "defaultRoles", + Entity.TEAM, origTeam.getId(), - updatedTeam.getId(), Relationship.HAS, Entity.ROLE, origDefaultRoles, updatedDefaultRoles); } - - private void updateEntityRelationships( - String field, - UUID origId, - UUID updatedId, - Relationship relationshipType, - String toEntityType, - List origRefs, - List updatedRefs) - throws JsonProcessingException { - List added = new ArrayList<>(); - List deleted = new ArrayList<>(); - if (!recordListChange(field, origRefs, updatedRefs, added, deleted, entityReferenceMatch)) { - // No changes between original and updated. - return; - } - // Remove relationships from original - daoCollection - .relationshipDAO() - .deleteFrom(origId.toString(), Entity.TEAM, relationshipType.ordinal(), toEntityType); - // Add relationships from updated - for (EntityReference ref : updatedRefs) { - addRelationship(updatedId, ref.getId(), Entity.TEAM, toEntityType, relationshipType); - } - updatedRefs.sort(EntityUtil.compareEntityReference); - origRefs.sort(EntityUtil.compareEntityReference); - } } } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java index 2729fe101dd..f552883099c 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java @@ -172,7 +172,7 @@ public class UserRepository extends EntityRepository { .findTo(user.getId().toString(), Entity.USER, Relationship.FOLLOWS.ordinal(), toBoolean(toInclude(user)))); } - public List validateRoles(List roleIds) throws IOException { + public List validateRolesByIds(List roleIds) throws IOException { if (roleIds == null) { return Collections.emptyList(); // Return an empty roles list } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java index 65932e5f641..12256aec1d2 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java @@ -88,6 +88,7 @@ public class GlossaryResource { public static Glossary addHref(UriInfo uriInfo, Glossary glossary) { glossary.setHref(RestUtil.getHref(uriInfo, COLLECTION_PATH, glossary.getId())); Entity.withHref(uriInfo, glossary.getOwner()); + Entity.withHref(uriInfo, glossary.getReviewers()); return glossary; } @@ -110,7 +111,7 @@ public class GlossaryResource { } } - static final String FIELDS = "owner,tags"; + static final String FIELDS = "owner,tags,reviewers"; public static final List ALLOWED_FIELDS = Entity.getEntityFields(Glossary.class); @GET diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java index 1e3acf53f3f..9dfaaf0bc19 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java @@ -434,6 +434,6 @@ public class UserResource { .withUpdatedBy(securityContext.getUserPrincipal().getName()) .withUpdatedAt(System.currentTimeMillis()) .withTeams(dao.validateTeams(create.getTeams())) - .withRoles(dao.validateRoles(create.getRoles())); + .withRoles(dao.validateRolesByIds(create.getRoles())); } } diff --git a/catalog-rest-service/src/main/resources/json/schema/api/data/createGlossary.json b/catalog-rest-service/src/main/resources/json/schema/api/data/createGlossary.json index fc9cba530d2..e187391c691 100644 --- a/catalog-rest-service/src/main/resources/json/schema/api/data/createGlossary.json +++ b/catalog-rest-service/src/main/resources/json/schema/api/data/createGlossary.json @@ -18,10 +18,10 @@ "type": "string" }, "reviewers": { - "description": "User names of the reviewers for this glossary.", + "description": "User references of the reviewers for this glossary.", "type": "array", "items": { - "type": "string" + "$ref": "../../type/entityReference.json" } }, "owner": { diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/data/glossary.json b/catalog-rest-service/src/main/resources/json/schema/entity/data/glossary.json index 0f489acf295..b14a3386c27 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/data/glossary.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/data/glossary.json @@ -2,7 +2,7 @@ "$id": "https://open-metadata.org/schema/entity/data/glossary.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "Glossary", - "description": "This schema defines the Glossary entity based on SKOS.", + "description": "This schema defines the Glossary entity. A Glossary is collection of hierarchical GlossaryTerms.", "type": "object", "definitions": { "name": { @@ -47,10 +47,10 @@ "$ref": "../../type/basic.json#/definitions/href" }, "reviewers": { - "description": "User names of the reviewers for this glossary.", + "description": "User references of the reviewers for this glossary.", "type": "array", "items": { - "type": "string" + "$ref": "../../type/entityReference.json" } }, "owner": { diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/data/glossaryTerm.json b/catalog-rest-service/src/main/resources/json/schema/entity/data/glossaryTerm.json index d7a04f9765f..815f43876aa 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/data/glossaryTerm.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/data/glossaryTerm.json @@ -2,7 +2,7 @@ "$id": "https://open-metadata.org/schema/entity/data/glossaryTerm.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "GlossaryTerm", - "description": "This schema defines the Glossary term entities.", + "description": "This schema defines te Glossary term entities.", "type": "object", "definitions": { "name": { @@ -94,10 +94,6 @@ "description": "User who made the update.", "type": "string" }, - "skos": { - "description": "SKOS data in JSON-LD format", - "type": "string" - }, "href": { "description": "Link to the resource corresponding to this entity.", "$ref": "../../type/basic.json#/definitions/href" diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java index 5a9e3edb012..3d3dafd6025 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java @@ -1952,7 +1952,14 @@ public abstract class EntityResourceTest extends CatalogApplicationTest { for (EntityReference expected : expectedList) { EntityReference actual = actualList.stream().filter(a -> EntityUtil.entityReferenceMatch.test(a, expected)).findAny().orElse(null); - assertNotNull(actual, "Expected entity " + expected.getId() + " not found"); + assertNotNull(actual, "Expected entity reference " + expected.getId() + " not found"); + } + } + + protected void assertStrings(List expectedList, List actualList) { + for (String expected : expectedList) { + String actual = actualList.stream().filter(a -> EntityUtil.stringMatch.test(a, expected)).findAny().orElse(null); + assertNotNull(actual, "Expected string " + expected + " not found"); } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryResourceTest.java index 074edbff273..08113c8dd1d 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryResourceTest.java @@ -22,10 +22,12 @@ import static org.openmetadata.catalog.util.TestUtils.assertListNull; import java.io.IOException; import java.net.URISyntaxException; +import java.util.List; import java.util.Map; import org.apache.http.client.HttpResponseException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestMethodOrder; import org.openmetadata.catalog.Entity; @@ -33,8 +35,12 @@ import org.openmetadata.catalog.api.data.CreateGlossary; import org.openmetadata.catalog.entity.data.Glossary; import org.openmetadata.catalog.jdbi3.GlossaryRepository.GlossaryEntityInterface; import org.openmetadata.catalog.resources.EntityResourceTest; +import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.FieldChange; +import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class GlossaryResourceTest extends EntityResourceTest { @@ -57,6 +63,26 @@ public class GlossaryResourceTest extends EntityResourceTest expectedRefs = (List) expected; + List actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class); + assertEntityReferencesFieldChange(expectedRefs, actualRefs); + } else { + assertCommonFieldChange(fieldName, expected, actual); + } } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResourceTest.java index f1424bd1726..2eb707af686 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResourceTest.java @@ -50,10 +50,14 @@ import org.openmetadata.catalog.entity.data.GlossaryTerm; import org.openmetadata.catalog.jdbi3.GlossaryRepository.GlossaryEntityInterface; import org.openmetadata.catalog.jdbi3.GlossaryTermRepository.GlossaryTermEntityInterface; import org.openmetadata.catalog.resources.EntityResourceTest; +import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.FieldChange; import org.openmetadata.catalog.util.EntityUtil; +import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.ResultList; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class GlossaryTermResourceTest extends EntityResourceTest { @@ -178,6 +182,28 @@ public class GlossaryTermResourceTest extends EntityResourceTest expectedRefs = (List) expected; + List actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class); + assertEntityReferencesFieldChange(expectedRefs, actualRefs); + } else if (fieldName.equals("synonyms")) { + @SuppressWarnings("unchecked") + List expectedRefs = (List) expected; + List actualRefs = JsonUtils.readObjects(actual.toString(), String.class); + assertStrings(expectedRefs, actualRefs); + } else { + assertCommonFieldChange(fieldName, expected, actual); + } } }